\documentclass[12pt,a4paper,titlepage]{article}
\usepackage{polski}
\usepackage[utf8]{inputenc}
\usepackage{url}
\usepackage{cite}
\usepackage{textcomp}
\usepackage[section]{placeins}
\usepackage[pdftex]{graphicx}
\usepackage{longtable}
\usepackage{color}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{caption}
\linespread{1.3} %1.3 do interlinii 1.5

\addtolength{\textwidth}{3cm}
\addtolength{\hoffset}{-1.5cm}
\addtolength{\textheight}{3cm}
\addtolength{\voffset}{-1.5cm}

\title{Analiza nierelacyjnych baz danych.}
\author{Paweł Burzyński}
\date{\today}

% http://stackoverflow.com/questions/741985/latex-source-code-listing-like-in-professional-books

\lstset{
	basicstyle=\footnotesize\ttfamily
}

\DeclareCaptionFont{white}{\color{white}}
\DeclareCaptionFormat{listing}{\colorbox{gray}{\parbox{\textwidth}{#1#2#3}}}
\captionsetup[lstlisting]{format=listing,labelfont=white,textfont=white}

\begin{document}

%\newcommand{\linia}{\rule{\linewidth}{0.4mm}}
%\begin{titlepage}
%
%    \begin{center}\LARGE
%    POLITECHNIKA WROCŁAWSKA\\
%    WYDZIAŁ ELEKTRONIKI\\[1mm]
%    \end{center}
%    
%    
%    \rule{\linewidth}{0.2mm}
%
%    KIERUNEK: Informatyka \\
%    \noindent SPECJALNOŚĆ: Inżynieria systemów informatycznych
%    
%    \begin{center}\huge
%		PRACA DYPLOMOWA \\
%		MAGISTERSKA
%    \end{center}
%    
%    \vspace{3cm}
%    \noindent\linia
%    \begin{center}
%      \LARGE \textsc{\@title}
%         \end{center}
%     \linia
%    \vspace{0.5cm}
%    \begin{flushright}
%    \begin{minipage}{5cm}
%    \textit{\small Autor:}\\
%    \normalsize \textsc{\@author} \par
%    \end{minipage}
%    \vspace{5cm}
%     {\small Praca wykonana pod przewodnictwem:}\\
%         dr Tomasz Słupiński
%     \end{flushright}
%    \vspace*{\stretch{6}}
%    \begin{center}
%    
%    \end{center}
%
%\end{titlepage}


\section*{Streszczenie}

Praca ta stanowi opis badań oraz wyniki analizy nierelacyjnych baz danych. Składa się z trzech rozdziałów, opisujących kolejno wybrane systemy bazodanowe, projekt autorskiego rozwiązania typu 
\textit{NoSQL} oraz opracowanie pomiarów szybkości tych systemów. Część analityczna skupia się w szczególności na modelu danych, reprezentowanym przez poszczególne systemy oraz algorytmach funkcjonowania
w środowisku rozproszonym. Opis autorskiego rozwiązania opatrzony jest wnikliwą analizą problematyki projektowania aplikacji z uwzględnieniem opisu zastosowanych algorytmów oraz wzorców projektowych.
Ostatnia część opisuje wyniki szybkości analizowanych systemów w takich operacjach jak zapis, odczyt, uaktualnienie oraz kasowanie danych.

\vspace{2cm}

\section*{Abstract}

This paper describes analysis and tests, that have been done on various non relational databases. It is divided into three chapters, the first chapter covers databases analysis, the second one describes
authors \textit{NoSQL} paradigm interpretation and the third one contains tests results and its interpretation. 
The analysis chapter focuses mainly on two aspects of each database. The first one is the data model 
and the second one are algorithms that enabled these systems to work in a distributed environment. 
This chapters output had its reflect in the work described in the next part, which covers the implementation and the design, with respect to algorithms and design patterns, used in authors own \textit{NoSQL}
system implementation. The last chapter focuses on the performance issues of analyzed databases, such as speed of: create, read, update and delete operations.

\newpage

\tableofcontents

\newpage



\section{Wstęp}

W dzisiejszych czasach obserwujemy bardzo gwałtowny przyrost ilości gromadzonych danych.
Facebook w 2010 roku posiadał bazę danych wielkości 21PB \cite{hadoop_facebook_cluster_1}, obsługiwaną przez \textit{Hadoop Framework}.
Co więcej, rok później ogłoszono, że wielkość tej bazy znacznie wzrosła i wynosi teraz 30PB danych.
\cite{hadoop_facebook_cluster_2}
Jak łatwo zauważyć, oznacza to przyrost o 9PB w ciągu roku, czyli około jednego terabajta w godzinę.

\par
Taka ilość danych nigdy dotąd nie była ani gromadzona ani analizowana.
Szczególnym problemem jest szybki zapis informacji. 
Tradycyjne rozwiązania, przy tak dużej wymaganej wydajności, nie znajdują zastosowania.
Były one projektowane z myślą o skalowaniu poprzez zwiększenie mocy obliczeniowej jednostki, na której pracują.
W dzisiejszych czasach znacznie taniej oraz łatwiej jest dodać kolejną maszynę niż zwiększać moc obliczeniową
już posiadanej. Natomiast w przypadku, gdy wymagana wydajność przewyższa moc obliczeniową istniejących procesorów oraz dysków, 
jest to wręcz niemożliwe.

\par
Z tego względu w ostatnich latach coraz większa rolę w zarządzaniu bazami danych o bardzo dużej wielkości zyskują systemy
oparte o \textit{NoSQL}. Termin ten został użyty po raz pierwszy przez Carlo Strozzi w 1998 roku w odniesieniu 
do swojej relacyjnej bazy danych, nie posiadającej jednak dostępu w języku SQL \cite{nosql_definition}.
Od tamtego czasu nazwa \textit{NoSQL} została przyjęta jako określenie systemu bazodanowego nie bazującego na podejściu relacyjnym oraz języku SQL.
Zbiór baz tego typu zawiera w sobie 
dokumentowe bazy danych, 
grafowe bazy danych, 
bazy danych typu klucz-wartość oraz wiele innych.

\par
Pierwszymi bazami danych typu \textit{NoSQL}, posiadającymi komercyjne znaczenie były \textit{Google BigTable} \cite{bigtable-paper} oraz 
\textit{Amazon Dynamo} \cite{dynamo-paper}. Obydwa te rozwiązania były oparte na modelu danych typu klucz-wartość.
\textit{Google BigTable} jest wykorzystywany jako podstawowa baza danych w wielu usługach firmy Google jak na przykład
\textit{Google Maps} lub \textit{Google AppEngine} \cite{bigtable-appengine}. Baza danych Amazon Dynamo została niedawno dodana jako 
usługa dla użytkowników chmury Amazon \cite{dynamo-aws}.

\par
Bazy \textit{NoSQL} cechują się dużą szybkością działania oraz łatwością skalowania wydajności poprzez dystrybucję na wiele niezależnych maszyn, 
a co za tym idzie, idealnie nadają się
do zastosowania w klastrach obliczeniowych. Posiadają one bardzo szybkie mechanizmy zapisu oraz odczytu danych. 
Co więcej, większość z nich umożliwia uruchamianie zadań typu \textit{Map/Reduce}. Algorytm ten został zaczerpnięty 
z funkcyjnych języków programowania oraz szczegółowo opisany w specjalnym dokumencie opracowanym przez Google 
\cite{map-reduce}. Opiera się on na założeniu, że większy problem może zostać rozwiązany poprzez dekompozycję go na szereg mniejszych oraz 
dystrybucję na niezależne maszyny. Krok ten nazywamy operacją \textit{Map}. 
Krok \textit{Reduce} polega na scaleniu rozwiązań cząstkowych w rozwiązanie globalne.
Przykładem tego podejścia może być wyszukiwanie maksymalnej liczby w pewnym skończonym ciągu.
W pierwszym kroku dzielimy cały ciąg na skończoną ilość podciągów a następnie wyszukujemy w każdym z tych podciągów maksimum.
W drugim kroku maksimum globalne otrzymujemy jako maksimum z maksimów lokalnych.
Wzorzec ten został opracowany z myślą o równoległym przetwarzaniu w środowisku rozproszonym,
dzięki czemu podczas analizy danych wszystkie węzły bazy mogą skutecznie wykorzystać całą moc klastra.

\par
Nie każdy system wymaga, aby dane przez niego przechowywane posiadały relacyjną strukturę. Co więcej, duża ilość
systemów informatycznych jest tworzona w oparciu o paradygmat obiektowy, który nie zawsze pokrywa się z paradygmatem 
relacyjnym. Generuje to wiele problemów wynikających z natury konfliktu paradygmatycznego.
Koronnym przykładem jest traktowanie wartości \textit{NULL} w językach SQL oraz \textit{null} w imperatywnych językach programowania, posiadających swoje korzenie w
języku C. Kolejnym problemem, jaki można napotkać podczas konwersji danych z modelu relacyjnego do obiektowego, jest 
sam fakt mapowania kolumn tabeli do właściwości oraz pól w klasach. Należy pamiętać, że w modelu relacyjnym nie istnieje pojęcie obiektu.
Projektant systemu musi w sposób arbitralny określić, w jaki sposób mają być one odwzorowane. Implikacją braku obiektów w systemach relacyjnych
są również trudności z odwzorowaniem dziedziczenia oraz polimorfizmu klas. 
Z tego względu powstały narzędzia typu \textit{ORM}, które zmniejszyły problem, jednak go nie rozwiązały
\cite{vietnam-of-computer-science}. W dzisiejszych czasach coraz popularniejsze staje się podejście typu \textit{CodeFirst} dostępne między innymi w
\textit{Entity Framework} \cite{ef_introduces_codefirst} oraz \textit{NHibernate} \cite{nhibernate_schemaexport}, które dodatkowo redukuje problem,
gdyż projektant systemu nie musi martwić się o schemat bazy danych. Rozwiązanie to nadaje się jednak jedynie do systemów o małym oraz średnim obciążeniu.
Istnieje inne rozwiązanie problemu mapowania. Przy zastosowaniu dokumentowych baz danych, jak na przykład \textit{RavenDB},
nie występuje potrzeba korzystania z bibliotek typu \textit{ORM}.
Model danych tych systemów bazodanowych wspiera paradygmat obiektowy.

\par
Trzeba jednak pamiętać, że większość baz danych typu \textit{NoSQL} nie nadaje się do każdego zastosowania.
Przede wszystkim, większość z nich nie wspiera zasady ACID, która została opisana przez Jima Greya w książce \cite{acid} i opisuje
cztery zasady, które muszą być spełnione, aby dane zawarte w bazie były spójne. Z tego względu, bazy danych \textit{NoSQL}, zupełnie nie nadają się
do zastosowań, w których cecha ta jest kluczowa, jak na przykład banki oraz systemy finansowe.

\par
Zastosowanie nierelacyjnej bazy danych w projekcie może nie tylko przynieść korzyści wynikające z przyspieszenia działania
systemu, lecz również z uproszczenia implementacji. Model danych systemu \textit{Cassandra}, oparty o zbiory klucz-wartość z różnymi
atrybutami dla każdej encji, idealnie nadaje się do systemu, w którym zbieramy informacje o pewnych zdarzeniach, które jednak
posiadają bardzo ograniczony zakres cech wspólnych.

\par
Temat baz danych typu \textit{NoSQL} jest relatywnie nowy oraz niezbadany. Istnieje jednak w nim duży potencjał,
zwłaszcza jeśli weźmiemy pod uwagę szybki rozwój portali społecznościowych, takich jak \textit{Facebook} oraz \textit{Twitter}, których model danych
idealnie nadaje się do wykorzystania tego typu podejścia. Ich rozwój dostarcza również bezcennych informacji na temat tego, w jakim stopniu 
rozwiązania \textit{NoSQL} sprawdzają się w środowisku produkcyjnym. Dodatkowym aspektem, przemawiającym za podjęciem się dogłębnej analizy tego tematu,
jest jego wsparcie dla modelu obliczeń oraz operacji rozproszonych, prezentowanych przez bazy danych \textit{NoSQL}. W dzisiejszych czasach zwiększenie mocy obliczeniowej komputerów dokonuje się poprzez
dodanie nowej jednostki obliczeniowej, a nie przez zwiększenie mocy już istniejącej.

\par
Wszystkie te aspekty sprawiły, że zdecydowano się podjąć zadania dogłębnej analizy rozwiązań typu \textit{NoSQL}, z naciskiem
na ich wydajność oraz możliwości zastosowania w różnego rodzaju aplikacjach.


\subsection{Cel oraz struktura pracy}
Celem pracy jest analiza nierelacyjnych baz danych, porównanie ich z rozwiązaniem relacyjnym oraz zaprojektowanie i 
zaimplementowanie własnej bazy danych, opartej o doświadczenia oraz syntezującej zalety analizowanych rozwiązań.

\par
Projektowany system będzie stanowić implementację bazy danych typu \textit{NoSQL}, nastawioną na zastosowanie w aplikacjach 
przemysłowych, takich jak akwizycja danych pomiarowych oraz przechowywanie danych historycznych, opisujących pewne procesy wytwórcze. 
Z tego względu najważniejsza będzie jej wysoka dostępność oraz bezpieczeństwo, przechowywanych danych.
Zaimplementowane zostaną w niej mechanizmy zapewniające integralność danych \cite{acid} oraz bezpieczeństwo polegające na
przechowywaniu danych na wielu komputerach jednocześnie.

\par
Praca ta podzielona została na trzy części.
Pierwszą z nich stanowi analiza najpopularniejszych rozwiązań typu \textit{NoSQL}, takich jak \textit{RavenDB}, \textit{MongoDB} oraz \textit{Cassandra},
pod względem wydajności, modelu danych oraz możliwości wykorzystania ich w kontekście aplikacji internetowych, 
tworzonych na platformę \textit{.NET}.

\par
Druga zawiera projekt własnego rozwiązania opartego na wnioskach pochodzących z
analizy zawartej w pierwszej części. Przedstawiony w niej zostanie całkowity proces rozwoju systemu bazodanowego,
od specyfikacji, poprzez projekt, aż po implementację.

\par
Trzecia polega na porównaniu wydajności własnego rozwiązania, wybranej relacyjnej bazy danych oraz analizowanych rozwiązań typu \textit{NoSQL}.
Kryteria porównawcze zostaną zdefiniowane w oparciu o szybkość operacji \textit{CRUD}, takich jak zapis, odczyt, uaktualnienie danych, dodanie
nowego wpisu do bazy oraz prędkość wyszukiwania używając klucza. 

\par
W ostatnim rozdziale przedstawione jest syntetyczne podsumowanie osiągniętych rezultatów. Bazując na zgromadzonych danych opisuje on możliwe kierunki rozwoju baz danych \textit{NoSQL} oraz 
potencjalne alternatywy oraz obszary zastosowań.


\newpage
\section {Analiza wybranych nierelacyjnych baz danych}

W rozdziale tym zostanie dokonana wnikliwa analiza wybranych rozwiązań \textit{NoSQL}. 
W szczególności poddany analizie będzie model danych. Bazy danych \textit{NoSQL} nie posiadają żadnego spójnego modelu danych.
Istnieją typy nierelacyjnych baz danych, jak na przykład: \textit{bazy obiektowe} lub \textit{słowniki klucz wartość}, jednak
nawet w obrębie przedstawicieli tych podzbiorów można znaleźć pewne istotne różnice.

\par
Kolejnym analizowanym aspektem będzie dostępność oraz jakość implementacji bibliotek klienckich.
Jest rzeczą oczywistą, że aby skomunikować się z bazą danych potrzebna jest pewnego rodzaju biblioteka obudowująca
skomplikowane wywołania oraz serializację danych transferowanych od bazy danych do aplikacji klienckiej.
Dodatkowo ważne jest, aby biblioteki klienckie były dostępne przynajmniej w najpopularniejszych językach programowania, jak 
na przykład \textit{C\#}, \textit{Java}, \textit{Python} lub \textit{PHP}. Dzięki temu wybór bazy danych nie ogranicza nam języka, 
w jakim możemy zaimplementować aplikację kliencką.

\par
Jak zostało zaznaczone we wstępie, jedną z głównych zalet baz danych typu \textit{NoSQL} jest ich wsparcie dla działania
w środowisku rozproszonym. Z tego względu każda z baz danych zostanie przeanalizowana pod kątem wspierania zadań typu \textit{Map/Reduce},
jak również partycjonowania oraz redundancji danych. Ta ostatnia własność jest szczególnie ważna, jeśli chcemy zwiększyć bezpieczeństwo systemu.
Dzięki dystrybucji danych na różne maszyny uodparniamy się na awarie pojedynczych węzłów komputerowych. 
W wielu rozproszonych systemach występuje tak zwana zasada lokalności operacji. Polega ona na prostej obserwacji, że poszczególne węzły
sieci w przypadku ogólnym nie dostają równomiernej ilości zapytań o cały zbiór danych. Na przykład baza danych tablic rejestracyjnych Województwa 
Dolnośląskiego jest częścią większej, ogólnopaństwowej infrastruktury posiadającej informacje o wszystkich tablicach rejestracyjnych w Polsce. 
Znaczna większość zapytań do tej bazy danych dotyczy jednak tablic rejestracyjnych jedynie Województwa Dolnośląskiego. 
Z tego względu podczas projektowania tego systemu można było te dane poddać partycjonowaniu ze względu na województwo z jakiego pochodzą.
W wyniku tej operacji baza danych trzymana lokalnie we Wrocławiu posiada jedynie informacje dotyczące Województwa Dolnośląskiego,
a w przypadku zapytania o rejestrację z Województwa Zachodniopomorskiego, zapytanie zostaje przekierowane na inny węzeł sieci.

\par
Ostatnim bardzo ważnym aspektem analizy jest podsumowanie każdej bazy danych, ze szczególnym uwzględnieniem cech szczególnych każdego z rozwiązań.
Ze względu na dużą różnorodność rozwiązań \textit{NoSQL}, niemalże każde z nich posiada pewne cechy szczególnie zasługujące na uwagę.
Stanowią one bardzo często rozszerzenie pewnego modelu danych lub mechanizmy zapewniające dodatkową integralność danych.
Najlepsze pod względem zastosowań przemysłowych, takich jak akwizycja oraz przechowywanie danych pomiarowych pewnych procesów,
cechy szczególne analizowanych baz danych zostaną zaimplementowane w systemie \textit{InDB}.


\subsection {RavenDB}

\textit{RavenDB} jest dokumentową bazą danych, w której dane przechowywane są w postaci obiektów \textit{JSON}.
Została ona w całości stworzona w oparciu o technologię \textit{.NET} oraz język \textit{C\#}, co jest rzadkością pośród rozwiązań tego typu.
Z tego względu wspiera ona wyszukiwanie elementów poprzez zastosowanie technologii \textit{LINQ}.
Chociaż jej kod źródłowy jest rozprowadzany na licencji \textit{Open Source}, to do zastosowań komercyjnych potrzebne jest 
wykupienie licencji \cite{ravendb_pricing}.

\par
Kolejną z cech, która wyróżnia tę bazę danych, jest wsparcie dla zasady \textit{ACID} \cite{acid}. 
Co prawda jest ono niepełne, co zostanie opisane w dalszej części pracy, 
jednak większość analizowanych baz danych nie posiada tej właściwości wcale, w związku z pewnym spadkiem wydajności, wynikającym z 
pilnowania integralności danych.
Dostęp do jej zasobów można osiągnąć przy pomocy prostego \textit{API}, opartego na protokole \textit{RESTful} \cite{restful}.
Jest on bardzo przystępny ze względu na niezależność od konkretnej implementacji oraz jasny i dobrze udokumentowany algorytm dostępu,
oparty o protokół \textit{HTTP}.
Baza ta radzi sobie bardzo dobrze w środowisku rozproszonym. Wspiera partycjonowanie oraz replikację danych, jak również umożliwia 
uruchamianie zadań na wielu węzłach jednocześnie.

\par
Ze względu na nietypową technologię dla tego typu systemów, wsparcie transakcji oraz przystępne \textit{API}, jak również 
funkcjonalności związane z działaniem w środowisku rozproszonym, zdecydowano się uwzględnić tę bazę danych w analizie.

\subsubsection {Architektura}

Baza danych \textit{RavenDB}, jak praktycznie każdy tego typu system, składa się z aplikacji serwera oraz klienta.
Serwer odpowiedzialny jest za przechowywanie danych, natomiast biblioteka kliencka umożliwia wywoływanie natywnych
metod \textit{RESTful API} poprzez odpowiednie klasy opakowujące.

\subsubsection*{Tryby działania}

\par
Bardzo ciekawą własnością serwera \textit{RavenDB} jest możliwość działania w różnych trybach.
W pierwszym z nich działa on jako normalna usługa \textit{Windows}. Jest on w pełni samowystarczalny oraz nie potrzebuje żadnych 
innych programów stanowiących jego środowisko uruchomienia. W ten sam sposób działa \textit{MSSQL Server} oraz wiele innych dużych, 
relacyjnych systemów baz danych. Pewną modyfikacją tego trybu działania jest uruchomienie aplikacji pod konsolą. Możliwość ta 
przydaje się znacznie podczas debugowania aplikacji.

\par
W drugim trybie działa on jako aplikacja uruchomiona za pomocą serwera \textit{HTTP}, wbudowanego w system \textit{Windows} - \textit{IIS} \cite{iis_overview}.
Ponieważ natywnym \textit{API} tej bazy danych jest \textit{RESTful} oparty na protokole \textit{HTTP}, jest rzeczą oczywistą, że uruchomienie go 
za pomocą lokalnego serwera \textit{www} powinno być możliwe. Co więcej, powinno nieść to za sobą wzrost wydajności, ponieważ serwer \textit{IIS} jest zoptymalizowany
pod kątem przetwarzania wiadomości \textit{HTTP} oraz \textit{HTTPS}. Odpowiada za to specjalny moduł jądra systemu operacyjnego \textit{Windows} o
nazwie \textit{HTTP.sys} \cite{iis_overview}.

\par
W trzecim trybie działa jako integralna część tworzonej aplikacji. Jest to tryb bardzo przydatny, gdy projektowana przez nas aplikacja ma 
bardzo ograniczone zasoby pamięci oraz procesora do wykorzystania. W wielu przypadkach jest również niepotrzebne uruchamianie osobnej bazy danych do
przechowywania jedynie niewielkiej ilości danych, a z drugiej strony nie chcemy tracić wszystkich uproszczeń oraz mechanizmów jakie zapewnia nam baza danych.
Przykładem relacyjnej bazy danych, która działa również jako biblioteka w przestrzeni aplikacji jest \textit{SQLite} \cite{sqlite_overview}.
Rozwiązanie to jest bardzo popularne i stosowane przez największe firmy z całego świata \cite{sqlite_users}. Jest ono wykorzystywane między innymi przez firmę 
\textit{Google} w systemie operacyjnym \textit{Android} do przechowywania danych aplikacji oraz w przeglądarce \textit{Opera} jako sposób przechowywania niektórych danych
przeglądarki i zapisanych ustawień.

\subsubsection*{Mechanizmy trwałego zapisu}

\par
\textit{RavenDB} zawiera dwa mechanizmy zapisu danych na dysk. Pierwszym z nich jest \textit{Esent}. Jest to biblioteka rozwijana przez \textit{Microsoft},
umożliwiająca zapisywanie danych w zindeksowanej formie. Wszystkie operacje na niej odbywają się w sposób transakcyjny. Posiada ona również mechanizmy
zabezpieczające integralność danych na wypadek awarii systemu. Ze względu na wysoką wydajność, rozwiązanie to nadaje się do zastosowań produkcyjnych.
Jedynie silnik opierający się na \textit{Esent} jest oficjalnie rekomendowany do zastosowań nietestowych. Drugi silnik o nazwie \textit{Munin}, 
napisany w pełni w kodzie zarządzanym dla potrzeb tej bazy danych, jest wolniejszy oraz mniej wydajny niż \textit{Esent}, przez co jest rekomendowany
jedynie do celów testowych.

\subsubsection*{System wtyczek}

\par
Pomimo tego, że \textit{RavenDB} posiada bardzo bogaty zasób funkcji, zawsze istnieje możliwość, że znajdziemy taką, której brakuje.
Z tego względu postanowiono stworzyć specjalny system rozszerzeń o nazwie \textit{Bundles}. Instalacja każdej z wtyczek jest bardzo prosta i składa się z dwóch etapów.
Po pierwsze, należy przekopiować odpowiedni plik \textit{dll} do katalogu z wtyczkami. 
Jest on zdefiniowany jako globalne ustawienie serwera o nazwie \textit{Raven/PluginsDirectory}.
Kolejnym krokiem jest konfiguracja wtyczki. Większość z nich konfigurowana jest poprzez edycję specjalnie utworzonych dokumentów. Czasami po tych operacjach wymagany jest 
restart bazy danych, ze względu na konieczność przeładowania pewnych podstawowych modułów systemu. 

\par
Do najpopularniejszych rozszerzeń należą \textit{Quotas Bundle}, dzięki której można ograniczyć wielkość bazy danych, 
\textit{Versioning Bundle}, która przechowuje historie zmian na każdym dokumencie oraz \textit{More Like This Bundle}, która przy pomocy biblioteki \textit{Lucene} \cite{lucene_dot_net}
wyszukuje dokumenty podobne do podanego. Ze względu na analizę funkcjonowania tej bazy danych w środowisku rozproszonym, warte uwagi są dwa rozszerzenia umożliwiające 
partycjonowanie danych pomiędzy różne węzły oraz replikację. Zostaną one omówione w dalszej części pracy.

\subsubsection*{Zasada domyślnego bezpieczeństwa}

\par
Podczas projektowania systemu \textit{RavenDB} starano się trzymać zasady domyślnego bezpieczeństwa. Została ona opisana szczegółowo w pozycji \cite{release_it}.
Zgodnie z jej założeniami, system powinien pozwolić programiście na działanie mogące uszkodzić lub spowodować znaczne zmniejszenie szybkości, jednak tylko
wtedy, gdy programista tego zażąda \textit{explicite}. Zgodnie z tym założeniem, system domyślnie wprowadza pewne ograniczenia na liczbę dokumentów, które mogą zostać
przesłane przy pojedynczym zapytaniu, chyba, że programista, przy użyciu metody \textit{.Take()} w sposób jawny zmieni ich ilość. Domyślnie ilość przesyłanych dokumentów jest ograniczona do 
128 \cite{ravendb_safe_by_default}. Liczba zapytań podczas jednego połączenia z bazą danych (sesji) jest również ograniczona. Dzięki temu łatwiej jest wykryć elementy 
implementacji, które wykonują zbyt wiele zapytań. Odbija się to bowiem w sposób negatywny na wydajności aplikacji. Liczba zapytań do bazy danych, na które system 
domyślnie pozwala wynosi 30 \cite{ravendb_safe_by_default}. W przypadku przekroczenia tej ilości zgłoszony zostaje wyjątek.

\subsubsection{Metody zarządzania serwerem}

\par
Baza danych \textit{RavenDB} posiada bardzo wiele ustawień oraz parametrów, które można zmieniać w celu dostosowania wydajności oraz sposobu jej działania
do naszych potrzeb. Ponieważ program ten jest w całości napisany przy użyciu języka \textit{C\#} oraz platformy \textit{.NET}, korzysta on z domyślnej architektury
plików konfiguracyjnych tej platformy. Jeśli działa on w trybie aplikacji \textit{IIS}, wykorzystuje standardowy \textit{Web.config} aplikacji. W innych
przypadkach odczytuje swoje ustawienia z pliku \textit{Raven.Server.exe.config}. W przypadku zmian w tych plikach czasami występuje konieczność ponownego uruchomienia
aplikacji poprzez wydanie komendy \textit{Raven.Server.exe restart}, gdyż nie wszystkie rozszerzenia mogą na bieżąco monitorować zmiany w plikach konfiguracyjnych.

\par
Ustawienia konfiguracyjne zostały podzielone na kilka grup. 
\begin{itemize}
	\item Ustawienia dotyczące sposobu oraz priorytetu z jakim działają wątki bazy danych.
	
	\item Ustawienia mechanizmu indeksowania.
	
	\item Ustawienia sposobu trwałego zapisu danych. Przy ich pomocy można ustawić między innymi aktywny
	silnik zapisu danych, katalog, do którego dane zostaną zapisane oraz tryb transakcji.
	
	\item Preferencje protokołu \textit{HTTP}
	serwera \textit{RavenDB} oraz ustawienia silnika przechowywania danych \textit{Esent}.

\end{itemize}

Warto zauważyć, że każde ustawienie ma swoją wartość domyślną, dlatego nawet jeśli część konfiguracji ulegnie skasowaniu lub zniszczeniu, baza danych nadal jest w stanie 
funkcjonować. Szczegółowo wszystkie ustawienia zostały udokumentowane w pracy \cite{ravendb_settings}.

\subsubsection*{Kopie bezpieczeństwa}

\par
Bazę danych \textit{RavenDB} można poddawać operacji tworzenia kopii bezpieczeństwa oraz przywracania tej kopii. Pierwsza z tych operacji może odbywać się podczas
działania systemu. Do wykonania drugiej z nich system musi zostać wyłączony.
Istnieją dwa sposoby tworzenia kopii bezpieczeństwa. Pierwszy z nich jest oparty o mechanizm tworzenia migawek dysku. Jest on wbudowany w system \textit{Windows}
od wersji \textit{Windows XP} i nosi nazwę \textit{Volume Shadow Copy} \cite{windows_vss}. Z tego samego mechanizmu korzysta również \textit{MSSQL}, dzięki czemu
możliwe jest robienie kopii bezpieczeństwa działających systemów, za pomocą standardowych narzędzi administracyjnych systemu \textit{Windows} \cite{mssql_and_vss}.

\par
Drugi sposób opiera się na wykorzystaniu programu do robienia kopii bezpieczeństwa, dostarczonego przez twórców \textit{RavenDB}.
W przeciwieństwie do poprzedniego rozwiązania, wynikiem jego działania jest baza danych, ale z chwili, w której operacja tworzenia kopii zapasowej 
została zainicjowana. Warto zauważyć, że narzędzia do tworzenia kopii zapasowych nie są kompatybilne wstecz, to znaczy kopia zapasowa wykonana na 
systemie \textit{Windows 7} nie koniecznie będzie działać na systemie \textit{Windows XP}. Są jednak kompatybilne wprzód co oznacza, że w sytuacji odwrotnej
baza danych będzie działać poprawnie.

\par
W zależności od trybu w jakim działa baza danych, operacje tworzenia kopii zapasowej można rozpocząć na kilka sposobów, wywołując metodę \textit{StartBackup()}
klasy \textit{DocumentDatabase}, gdy baza danych działa w trybie wbudowanym w aplikację
lub poprzez wywołanie programu \textit{Raven.Backup.exe} w trybie, gdy baza danych działa jako osobny proces. Warto pamiętać, że narzędzie do tworzenia kopii bezpieczeństwa musi działać
z uprawnieniami administratora. Bardzo ciekawą właściwością jest możliwość wywołania operacji tworzenia kopii bezpieczeństwa za pomocą odwołania się do adresu
\textit{/admin/backup}. Spowoduje to asynchroniczne rozpoczęcie tworzenia kopii zapasowej.
 
\par
Operacja przywrócenia bazy danych do stanu, w którym wykonana została kopia zapasowa jest również prosta. W trybie wbudowanym należy wywołać metodę
\textit{Restore()} klasy \textit{DocumentDatabase}, natomiast, gdy baza danych działa jako osobny program, należy uruchomić ją z parametrem \textit{-restore} oraz 
dodać źródło, z którego ma zostać pobrana kopia zapasowa. Warto zauważyć, że operacja przywrócenia kopii zapasowej, jest w przeciwieństwie do operacji jej tworzenia w pełni
synchroniczna oraz wymaga przełączenia jej w stan nieoperacyjny.

\par
Operacja tworzenia kopii zapasowej oraz jej odtwarzania powinna być wykorzystywana w przypadku, gdy chcemy uchronić nasze dane od zniszczenia.
Warto zauważyć, że nie zawsze pliki kopii bezpieczeństwa są kompatybilne pomiędzy różnymi wersjami systemów operacyjnych oraz tym bardziej wersjami bazy danych.
Dlatego, jeśli chcemy przenieść dane do innego systemu lub stworzyć kopię bezpieczeństwa niezależną od wersji systemu operacyjnego i instancji programu \textit{RavenDB},
powinniśmy skorzystać z narzędzi importu oraz eksportu.

\subsubsection*{Import oraz eksport danych}

\par
W celu wykonania eksportu oraz importu danych musimy skorzystać z osobnego programu o nazwie \textit{Smuggler}. Wynikiem jego działania jest pojedynczy plik
zawierający wszystkie dane dotyczące bazy, w szczególności indeksy, dokumenty w niej zawarte oraz załączniki. 
Co więcej, uwzględnia on również wszystkie zmiany dokonane w bazie podczas operacji eksportu.
Każdy z elementów można wykluczyć z operacji eksportu poprzez dodanie odpowiedniej opcji, na przykład \textit{--only-indexes} wyeksportuje informacje jedynie o indeksach.

\par
Gdy chcemy zaimportować dane z pliku eksportu, również powinniśmy skorzystać z programu \textit{Smuggler}. W przeciwieństwie do operacji przywracania kopii zapasowej,
baza danych \textit{RavenDB} może działać podczas operacji importu dokumentów. Należy jednak pamiętać o tym, że wszystkie istniejące dokumenty o duplikującym się kluczu
zostaną nadpisane przez te pochodzące z pliku eksportu.

\begin{figure}
\centering
\includegraphics{ravendb_the_studio.png}
\caption{Widok głównego ekranu \textit{The Studio}}
\label{ravendb_the_studio}
\end{figure}

\subsubsection*{Graficzne narzędzie dostępowe}

\par
Każdy większy system bazodanowy posiada pewnego rodzaju graficzne narzędzia dostępowe, umożliwiające edycję danych oraz zarządzanie konfiguracją. 
\textit{MSSQL} posiada \textit{Management Studio} \cite{mssql_management_studio}. \textit{RavenDB} również posiada tego typu narzędzie, jest ono jednak znacznie mniej 
rozbudowane niż \textit{MSSQL Management Studio} i nazywa się po prostu \textit{The Studio}. Posiada ono podstawową funkcjonalność pozwalającą na przeglądanie oraz edycję danych zawartych w bazie,
uruchamianie oraz ustawianie odpowiednich zadań oraz przeglądanie logów aplikacji. Zostało ono napisane przy pomocy technologii \textit{Silverlight}, z tego względu
dostęp do niego odbywa się poprzez przeglądarkę internetową. Brak w nim jednak narzędzi do bardziej wnikliwej analizy danych oraz przede wszystkim konfiguracji wtyczek.

\par
\textit{The Studio} jest podzielone na kilka sekcji. Po uruchomieniu wyświetla nam się sekcja podsumowująca działanie bazy danych. Zawiera ona przegląd ostatnio dodanych dokumentów.
\textit{The Studio} posiada również widok zawierający wszystkie dokumenty, w którym każdy z nich można edytować. Kolejny widok prezentuje informacje dotyczące wszystkich kolekcji. Dzięki
niemu możemy zobaczyć na przykład ile jest dokumentów w danej kolekcji lub skasować wszystkie dokumenty z danej kolekcji. Istnieje również widok, dzięki któremu możemy przetestować
działanie indeksów oraz dodać nowe. Importu oraz eksportu można dokonać korzystając z widoku zadań. Ostatnie dwa widoki dotyczą podsumowania działania systemu, w postaci wyświetlania 
logów oraz statystyki systemu, dotyczące ilości indeksów, stworzonych dokumentów oraz ilości zarejestrowanych błędów.




\subsubsection{Model danych}

\par
Kolejnym bardzo ważnym aspektem, który należy zanalizować, jest model logiczny przechowywanych danych.
Jak już zostało zaznaczone we wstępie, \textit{RavenDB} jest dokumentową bazą danych. To znaczy, że każda encja stanowi osobny dokument.
Każdy dokument jest identyfikowany przez klucz składający się zgodnie z konwencją z dwóch części. Pierwszą z nich jest nazwa typu dokumentu, natomiast kolejną z nich jest
identyfikator dokumentu w obrębie encji tego samego typu. Poprzez analogię można to porównać do nazwy tabeli oraz klucza głównego tej tabeli.
Warto zauważyć, że jest to tylko konwencja i użytkownik może zawsze stworzyć własny sposób nadawania identyfikatorów dokumentom.
Ważne jest żeby pamiętać o tym, że każdy identyfikator musi być unikalny w obrębie całej bazy danych. Jest to zwłaszcza istotne, jeśli weźmiemy pod uwagę fakt,
że \textit{RavenDB} w żaden sposób nie sprawdza czy klucze w obrębie bazy danych są unikalne. Jeśli spróbujemy dodać nowy dokument, którego klucz jest duplikatem już istniejącego,
system bazy danych nadpisze stary dokument nowym, bez żadnego ostrzeżenia.


\begin{figure}
\centering
\includegraphics{document_model}
\caption{Przykładowa encja w dokumentowym model danych.}
\label{document_model}
\end{figure}



\par
Jedną z ważniejszych rzeczy, o których należy pamiętać podczas projektowania baz danych opartych na \textit{RavenDB} jest fakt, że dokumenty, w odróżnieniu od wierszy 
bazy danych, nie mają struktury płaskiej. Każdy dokument może zawierać kolekcję podklas oraz referencje do innych klas. Taki graf obiektów, w przeciwieństwie do podejścia 
znanego z narzędzi typu \textit{ORM} i relacyjnych baz danych, nie jest rozdzielany w żaden sposób, tylko zapisywany w całości jako pojedynczy dokument. Z tego względu 
utrudniona jest implementacja kolekcji lub referencji współdzielonych przez różne obiekty. Zamiast referencji bezpośrednio do dokumentu, należy umieścić identyfikator 
dokumentu, do którego mamy zamiar się odwołać. \textit{RavenDB} nie zadba niestety o spójność danych w ten sam sposób, w jaki relacje dbają o spójność danych w relacyjnych bazach danych.
Stanowi to pewne odstępstwo od reguły \textit{ACID}.
Znaczy to, że mogą występować dokumenty posiadające odnośniki do nieistniejących dokumentów. Jest to dość kłopotliwa sytuacja i może powodować wiele problemów przy 
utrzymaniu logicznej spójności danych w bazie. Przy projektowaniu encji warto zastosować wzorzec architektoniczny agregatora opisany w książce \cite{aggregate_design_pattern}.
Zakłada on, że w modelu znajdują się pewne główne encje, zwane korzeniami oraz encje pomocnicze, które są stworzone oraz zorganizowane dookoła korzenia.
Dzięki temu pomiędzy poszczególnymi drzewami można zastosować odwołanie poprzez klucz, natomiast w powiązaniach encji z tego samego drzewa można zastosować 
zwykłe referencje obiektowe.


\par
Bardzo ważnym aspektem architektury oraz modelu danych bazy \textit{RavenDB} jest pojęcie kolekcji. Jest to pewien logiczny zbiór encji tego samego typu.
Można odnieść go przez pewną analogię do tabeli w relacyjnej bazie danych, jednak jedynie na poziomie logicznym. W relacyjnej bazie danych podział na 
tabele ma faktycznie fizyczne odwzorowanie w organizacji pliku bazy danych. W omawianej bazie danych kolekcje stanowią jedynie logiczny zbiór i nie mają 
żadnego znaczenia dla silnika bazy danych. Ma to swoje uzasadnienie w fakcie, że wszystkie encje są pozbawione schematu oraz w istocie są dokumentami tego samego typu,
toteż mogą być traktowane na równi.

\par
Każdy dokument w bazie danych przechowywany jest w formacie \textit{JSON}, opisanym dokładnie w pracy \cite{json_rfc}. Jest to bardzo minimalistyczny format, którego przejrzystość
jest znacznie większa dla człowieka niż \textit{XML}. Warto zauważyć, że autorzy tej bazy danych
skorzystali z biblioteki \textit{Json.NET}, której twórcą jest James Newton-King \cite{json_dot_net}. Jest ona bardzo wydajnym oraz prostym sposobem 
na serializację oraz deserializację danych w formacie \textit{JSON}, jak również jest w stanie wykonywać wyszukiwania \textit{LINQ} w zbiorach danych
dokumentów w tym formacie.

\par
Ponieważ wszystkie dokumenty przechowywane są w formie tekstowej, mogłoby się wydawać, że \textit{RavenDB} nie jest w stanie składować danych binarnych.
W celu rozwiązania tego problemu stworzono specjalny dodatkowy sposób przechowywania danych, w postaci załączników. Każdy załącznik jest po prostu jakimś 
zbiorem binarnych danych, umieszczanych w bazie danych. \textit{RavenDB} w żaden sposób nie analizuje semantycznej zawartości takich załączników.
Warto zauważyć, że jest to znacznie szybszy sposób przechowywania danych binarnych niż kodowanie ich tekstowo i zamieszczanie w dokumentach.
Należy jednak pamiętać, że dane binarne nie mogą być zbyt duże. Rozsądnym ograniczeniem, jakie należy przyjąć jest 10MB.
Pomijając aspekt małej wydajności, \textit{RavenDB} korzysta z biblioteki \textit{Esent},
która posiada pewne ograniczenia na wielkość kolumny, której zawartość nie może przekroczyć \textit{2GB} \cite{esent_columns_description}.

\par
W ostatnich latach we wszystkich językach programowania coraz większy nacisk kładzie się na elementy oraz mechanizmy meta-programowania, takie jak na przykład refleksja.
To samo tyczy się baz danych. \textit{MSSQL} zawiera w sobie specjalny zestaw widoków ze schematu \textit{sys}, który wraz z każdą kolejną wersją tego oprogramowania 
znacznie się rozszerza \cite{mssql_catalog_views}. Posiadają one wszystkie informacje na temat schematu bazy danych. 
Baza danych \textit{RavenDB} również posiada podobne mechanizmy. Każda encja w kolekcji jest rozszerzona o specjalne atrybuty, mówiące o jej strukturze.
Dzięki temu można w łatwy sposób dowiedzieć się, na podstawie encji, do jakiego typu ona należy.

\par
\textit{RavenDB} jest bazą danych pozbawioną schematu. Rozwiązuje to wiele problemów, znanych z relacyjnych baz danych, jednak wprowadza wiele nowych.
Jednym z nich jest utrudnione wyszukiwanie. W celu rozwiązania tego problemu wprowadzono rozszerzony mechanizm indeksów \cite{ravendb_indexes}.
Każdy indeks reprezentowany jest jako zapytanie \textit{LINQ}. Co ciekawe, są one uruchamiane w tle, a ich wyniki buforowane. W przypadku, gdy nowo dodane
dane zakłócają porządek indeksu, nie jest on przeliczany od razu, tylko po pewnym czasie. Jest to jeden z przykładów optymalizacji, mającej na celu 
przyspieszenie operacji \textit{CRUD} w stosunku do relacyjnych baz danych, który jednak odbija się na dokładności otrzymanych wyników.

\par
Taki sposób implementacji indeksowania przypomina bardziej widok zmaterializowany, znany między innymi z baz danych \textit{Oracle} \cite{oracle_materialized_view}. 
Dzięki temu uzyskuje się bardzo szybki dostęp do wyników wykonanych zapytań. Co więcej, wyniki działania indeksów są trzymane w postaci przejrzystej dla biblioteki 
\textit{Lucene} \cite{ravendb_indexes}. Służy ona do wyszukiwania danych w tekście oraz jest bardzo szybka.
Dzięki temu można uzyskać dostęp do bardzo szybkich mechanizmów późniejszego operowania na indeksach oraz ich przetwarzania, jak na przykład
pełne lub częściowe przeszukiwanie tekstu oraz przeszukiwanie tekstu na podstawie pewnego zakresu.

\par
\textit{RavenDB} posiada wsparcie dla systemu transakcji. Jest to bardzo rzadko spotykana cecha pośród baz tego typu. Dzięki temu nadaje się on do zastosowań 
wymagających od bazy danych spełnienia zasad \textit{ACID} \cite{acid}. Transakcje w bazie danych \textit{RavenDB} są realizowane dzięki wykorzystaniu mechanizmów z przestrzeni nazw
\textit{System.Transactions} oraz koordynatora transakcji rozproszonych \cite{msdtc}. Z tego względu wspiera on transakcje w środowisku rozproszonym, co jest wyjątkowo 
ważne, biorąc pod uwagę typowe obszary wdrożeń baz danych \textit{NoSQL}.


\subsubsection {Biblioteki klienckie}

Dostęp do \textit{RavenDB} odbywać się może w dwojaki sposób. Po pierwsze programista może skorzystać z natywnego \textit{RESTful API} lub
gotowej biblioteki, opakowującej odpowiednie wywołania w klasy \textit{.NET}. Niemalże każdy język programowania dostarcza pewnego rodzaju mechanizmy, pozwalające na 
połączenie się z witryną za pomocą protokołu \textit{HTTP}. Z tego względu pierwszy sposób jest możliwy do wykorzystania w praktycznie każdym języku programowania.
Jest on jednak odrobinę trudniejszy i wymaga wykonania wielu czynności, jak na przykład konwersja danych z formatu \textit{JSON} na instancje obiektów lub struktur.
Zastosowanie gotowej biblioteki stworzonej na platformę \textit{.NET} opakowuje wywołania tych metod w klasy oraz obiekty, dzięki czemu znacznie upraszcza pracę.

\subsubsection*{\textit{RESTful API}}

\par
Bezpośrednie połączenie za pomocą \textit{RESTful API} bardzo przydaje się przy okazji testowania bazy danych, zwłaszcza w połączeniu z narzędziem \textit{curl}, które 
jest w stanie wysłać dowolne zapytanie \textit{HTTP}. Przykładowo, jeśli chcemy pobrać jakiś dokument z naszego lokalnego serwera wystarczy wydać polecenie zaprezentowane na listingu \ref{rest_get_by_id}.

\begin{lstlisting}[label=rest_get_by_id,caption=Pobranie dokumentu z lokalnego serwera]
curl -X GET http://localhost:8080/docs/12
\end{lstlisting}



\par
W celu zrozumienia działania tego \textit{API}, najpierw należy zrozumieć cały koncept \textit{RESTful API}. Opiera się ono na zasadzie \textit{REST}, której fundamentalnym 
założeniem jest fakt, że każde zapytanie do serwera jest niezależne i serwer nie powinien w żaden sposób utrzymywać stanu połączenia pomiędzy dwoma zapytaniami. 
Podlega ono pod dużo szerszą zasadę tworzenia obiektów pozbawionych stanu, znaną między innymi z języków funkcyjnych \cite{fp_stateless}. 
Aplikacje tworzone przy wykorzystaniu takiego podejścia są znacznie luźniej skorelowane oraz dużo prostsze w rozbudowie. Co więcej, mamy pewność, że podczas testowania dwóch metod osobno
po ich złożeniu również otrzymamy poprawnie funkcjonujący program.

\par
Zgodnie z wymienionymi założeniami powstała specjalna technologia tworzenia web serwisów, opartych o \textit{RESTful API}.
Opiera się ona na wykorzystaniu metod protokołu \textit{HTTP} zgodnie z ich semantyką. Warto zauważyć, że przez wiele lat jedynie metody \textit{GET} oraz \textit{POST}
były w praktyce wykorzystywane. W tabeli \ref{restful_ravendb} przedstawiono krótki opis każdej wykorzystywanej metody zaczerpnięty z książki \cite{restful_web_services}.

\begin{table}
\begin{tabular}{ | l | p{6cm} | p{7cm} |}
\hline Metoda/Zasób & \url{http://localhost/collection} & \url{http://localhost/collection/11} \\ 
\hline GET & Pobranie całej kolekcji obiektów typu \textit{collection} & Pobranie pojedynczego elementu kolekcji, identyfikowanego przez klucz \textit{11} \\
\hline PUT & Nadpisanie kolekcji \textit{collection} przez nową & Nadpisanie pojedynczego elementu o identyfikatorze \textit{11} nowym \\
\hline POST & Stworzenie nowego elementu w kolekcji \textit{collection} & Stworzenie nowego wpisu w elemencie o identyfikatorze \textit{11} \\
\hline DELETE & Usunięcie całej kolekcji \textit{collection} & Usunięcie elementu o identyfikatorze \textit{11} z kolekcji \textit{collection} \\
\hline
\end{tabular}
\caption{\textit{RESTful API} w kontekście zastosowania w \textit{RavenDB}}
\label{restful_ravendb}
\end{table}

\subsubsection*{Biblioteka dostępowa dla \textit{.NET}}

Jak nietrudno zauważyć, korzystanie jedynie z \textit{RESTful API} byłoby niezmiernie ciężkie oraz w większości przypadków skutkowałoby stworzeniem 
własnych bibliotek opakowujących wywołania \textit{HTTP}. Z tego względu postanowiono stworzyć specjalne \textit{API} w \textit{.NET} \cite{ravendb_client_api}.
W swojej konstrukcji bazuje w dużej mierze na bibliotece \textit{ORM} o nazwie \textit{NHibernate}. Dostępna jest przez system instalacji bibliotek \textit{NuGet}
oraz opiera się na trzech podstawowych interfejsach: \textit{IDocumentStore}, \textit{IDocumentSession} oraz \textit{IDocumentQuery}.

\par
\textit{IDocumentStore} jest interfejsem reprezentującym całą bazę danych. Zgodnie z zaleceniami twórców oprogramowania powinna istnieć jedna instancja klasy implementującej
ten interfejs w całym programie, gdyż jego stworzenie zajmuje dużo czasu. Dostęp do niego może odbywać się jednocześnie z wielu wątków. Głównym zadaniem tego 
obiektu jest tworzenie instancji klas typu \textit{IDocumentSession}, które odpowiadają za interakcję z bazą danych.

\par
\textit{IDocumentSession} reprezentuje pojedyncze połączenie z bazą danych. Za jego pomocą możemy modyfikować stan bazy danych oraz wykonywać zapytania.
Warto pamiętać, że obiekty tego typu są bardzo łatwe do stworzenia, jednak dostęp do nich może odbywać się jedynie z jednego wątku jednocześnie. W przypadku
zgłoszenia wyjątku przez instancję tej klasy, należy założyć, że zachowanie wszystkich kolejnych metod jest niezdefiniowane i z obiektu takiego nie powinno się już korzystać.
Warto zauważyć, że klasa ta została stworzona w oparciu o wzorzec \textit{Unit of work} \cite{fowler}. Dzięki temu zmiany w bazie danych zostają zatwierdzone 
dopiero po wywołaniu metody \textit{SaveChanges()}. Zastosowanie tego wzorca bardzo ułatwia tworzenie aplikacji,
których metody biznesowe zachowują spójność danych w bazie.

\par
\textit{IDocumentQuery} jest obiektem reprezentującym pojedyncze zapytanie do bazy danych \textit{RavenDB}. Dzięki niemu możemy tworzyć zapytania do indeksów
oraz kasować lub modyfikować masowo dane.

\par
Najprostszym sposobem połączenia się do bazy danych jest utworzenie instancji obiektu \textit{DocumentStore} z odpowiednim adresem oraz jego inicjacja.
Przykładowy kod realizujący tę operację został zaprezentowany na listingu \ref{init_ravendb}.

\begin{lstlisting}[label=init_ravendb,caption=Procedura podłączenia do bazy danych \textit{RavenDB}]

var documentStore = new DocumentStore 
{ 
	Url = "http://localhost:8080/" 
};
documentStore.Initialize();

\end{lstlisting}

W celu uniknięcia konieczności podawania dokładnych danych połączenia w kodzie, możemy skorzystać z możliwości umieszczenia w pliku konfiguracyjnym aplikacji
łańcucha połączeniowego bazy danych \textit{RavenDB}. Zawiera on takie pola jak na przykład \textit{Url}, \textit{User/Password} oraz \textit{Database}. Dzięki nim, 
podczas instalacji tworzonej przez nas aplikacji, możemy dowolnie zindywidualizować sposób łączenia się z bazą danych.

\par
Do najważniejszych metod interfejsu \textit{IDocumentSession} należą: \textit{Load}, \textit{Delete} oraz \textit{Store}. Pierwsza z nich służy do wczytania 
obiektu z bazy danych do przestrzeni aplikacji. Przyjmuje ona argument będący kluczem istniejącego dokumentu. Jest to metoda generyczna, więc wymaga wyspecyfikowania
dodatkowo typu dokumentu, który chcemy wczytać. Klucz może być dowolnym obiektem, jednak najczęściej wykorzystywane są trzy typy \textit{int}, \textit{Guid} oraz \textit{string}.
Po wczytaniu obiekt możemy dowolnie modyfikować. W celu synchronizacji zmian z bazą należy wywołać wspomnianą metodę \textit{SaveChanges()}.

\par
W celu dodania nowego obiektu do bazy danych należy skorzystać z metody \textit{Store}. Należy jednak pamiętać, że w przypadku podania klucza, który już istnieje w bazie danych,
istniejący dokument zostanie nadpisany przez zapisywany bez żadnego ostrzeżenia. Z tego względu dobrą praktyką jest niepodawanie klucza jako argumentu tej metody, gdyż w tym przypadku
system przydzieli go automatycznie. Innym rozwiązaniem tego problemu jest zastosowanie klucza typu \textit{Guid}, który praktycznie zawsze jest unikalny \cite{uuid_rfc}.
Po wykonaniu tej metody również należy pamiętać o wywołaniu metody \textit{SaveChanges()}.

\par
Usunięcia dokumentu z bazy możemy dokonać w dwojaki sposób. Po pierwsze możemy wywołać metodę \textit{Delete} interfejsu \textit{IDocumentSession}, której jako argument 
podajemy dokument, który chcemy usunąć. Jest ona przydatna w przypadku, gdy posiadamy już załadowany dokument, np. jako wynik działania metody \textit{Load}.
Drugi sposób polega na wywołaniu metody \textit{Delete}, jednak nie interfejsu \textit{IDocumentSession}, a jego właściwości o nazwie \textit{Advanced.DatabaseCommands}.
Druga metoda \textit{Delete} wymaga podania jedynie klucza dokumentu i nie wymaga ładowania obiektu do przestrzeni aplikacji.
Należy jednak zwrócić uwagę, że w przeciwieństwie do pierwszej metody, nie wymaga ona potwierdzenia w postaci metody \textit{SaveChanges()} i działa natychmiastowo.

\par
Oprócz typowych metod zapisu oraz kasowania \textit{RavenDB} dostarcza również możliwość wywoływania zapytań na bazie danych. W tym celu stworzona została specjalna biblioteka
tłumacząca zapytania \textit{LINQ} na język zapytań \textit{RavenDB}. Na listingu \ref{ravendb_linq} zaprezentowano przykładowe zapytanie, którego wynikiem są jedynie osoby pełnoletnie.

\begin{lstlisting}[label=ravendb_linq,caption=Przykładowe zastosowanie zapytania \textit{LINQ} w bazie danych \textit{RavenDB}]
var res = from p in session.Query<People>()
          where p.Age > 18
          select p;
\end{lstlisting}

\par
Czasami istnieje potrzeba wykonania pewnego grupowego uaktualnienia lub skasowania danych spełniających pewien predykat. \textit{RavenDB} umożliwia taką opcję poprzez 
dwie metody omawianej wcześniej właściwości \textit{DatabaseCommands}, \textit{DeleteByIndex} oraz \textit{UpdateByIndex}. Obydwie przyjmują jako argument nazwę indeksu, 
na którym będą operować oraz specyfikację zadania. Jak już zostało wspomniane, indeksy w bazie danych \textit{RavenDB} działają odrobinę inaczej niż w relacyjnych bazach danych.
W przypadku dodania nowych danych, nie są przeliczane na bieżąco, lecz jako zadanie w tle. Z tego względu może wystąpić sytuacja, w której użytkownik będzie chciał wykonać operację
kasowania lub uaktualniania danych na indeksie, który nie zdążył się jeszcze zaktualizować. Domyślnie w takim przypadku operacja taka nie jest wykonywana, chyba, że użytkownik
\textit{explicite} uzna, że chce ją wykonać.

\par
Wszystkie omówione do tej pory metody działają w sposób synchroniczny. Istnieje jednak możliwość utworzenia również sesji bazy danych działającej asynchronicznie.
W tym celu zamiast metody \textit{OpenSession}, interfejsu \textit{IDocumentStore} należy wywołać metodę \textit{OpenAsyncSession}. Otrzymany w jej wyniku obiekt 
daje możliwość wykonywania operacji na bazie danych w sposób asynchroniczny. Ma to duże znaczenie jeśli nasza baza danych znajduje się na innym serwerze, a my nie chcemy
obciążać puli wątków lokalnego serwera \textit{IIS} przez wątki zawieszone w oczekiwaniu na zdalną operację.

\par
Dostęp do załączników umieszczonych w bazie danych również odbywa się poprzez wykorzystanie metod z właściwości \textit{DatabaseCommands}. W szczególności dany 
załącznik można skasować, uaktualnić lub utworzyć nowy. Co więcej, wspomniana właściwość stanowi najniższy poziom, na którym można komunikować się z bazą danych za 
pomocą omawianej biblioteki. Dzięki niej można wykonywać praktycznie każdą operację na dokumentach, załącznikach, indeksach oraz transakcjach, jak również 
niektóre zadania konfiguracyjne.

\subsubsection {Funkcjonowanie w środowisku rozproszonym}

\textit{RavenDB}, jak większość rozwiązań \textit{NoSQL}, został zaprojektowany z myślą o funkcjonowaniu w środowisku rozproszonym. W niniejszym rozdziale zostaną opisane 
niektóre mechanizmy, dotyczące tego obszaru funkcjonalności.

\subsubsection*{Replikacja}

\par
Pierwszym z nich jest replikacja. W celu zapewnienia większego bezpieczeństwa danych, wszystkie zasoby zgromadzone w jednym węźle bazie danych \textit{RavenDB} mogą być 
zreplikowane na inny. Co więcej, replikacja ta odbywa się w trybie multi-master a co za tym idzie, węzły mogą replikować swoje dane wzajemnie. Synchronizacja danych następuje w sposób
automatyczny, po zatwierdzeniu każdej transakcji. Jeśli jeden z węzłów bazy danych przestanie odpowiadać, \textit{RavenDB} wykrywa to i zwiększa interwał czasowy pomiędzy kolejnymi
próbami komunikacji. Dopiero, gdy węzeł znów zacznie odpowiadać, synchronizowane są wszystkie zmiany. Ponieważ cała synchronizacja odbywa się w sposób automatyczny,
nie są potrzebne żadne zabiegi administracyjne, żeby uszkodzony węzeł stał się znów w pełni funkcjonalny. 

\par
Omawiana wcześniej biblioteka kliencka również jest zaopatrzona w pewien mechanizm, umożliwiający przełączenie się pomiędzy węzłami bazy danych w przypadku
wykrycia usterki jednego z nich. Mechanizm ten nazywa się \textit{failover} i jest znany z innych systemów rozproszonych jak na przykład \textit{MSSQL} \cite{mssql_failover}.
Jest bardzo wygodny, gdyż zapewnia ciągłość działania systemu, bez potrzeby modyfikacji kodu aplikacji.

\par
W celu skonfigurowania replikacji, na węzłach bazy danych należy dokonać pewnych zmian w pliku konfiguracyjnym. Po pierwsze należy zdefiniować katalog z wtyczkami oraz 
koniecznie ustawić dostęp anonimowy na \textit{All}, tak jak przedstawiono w przykładzie na listingu \ref{ravendb_config}.

\begin{lstlisting}[label=ravendb_config,caption=Przykładowa konfiguracja bazy danych \textit{RavenDB}]
<appSettings>
  <add key="Raven/Port" value="*"/>
  <add key="Raven/DataDir" value="~\Data"/>
  <add key="Raven/AnonymousAccess" value="All"/>
  <add key="Raven/PluginsDirectory" value="D:\RavenDB\Plugins" />
</appSettings>
\end{lstlisting}

Następnie należy skopiować wtyczkę z katalogu Bundles o nazwie \textit{Raven.Bundles.Replication.dll}, do katalogu zdefiniowanego w poprzednim kroku. 
Po uruchomieniu serwera powinien pojawić się nowy dokument o nazwie \textit{Raven/Replication/Destinations}. Dalsza konfiguracja polega na jego edycji. 
Należy podać w nim serwery, na które dane powinny zostać zreplikowane, tak jak zostało to zilustrowane w listingu \ref{ravendb_config_replication}.

\begin{lstlisting}[label=ravendb_config_replication,caption=Przykładowa konfiguracja dokumentu replikacji]
{
  "Destinations": [
    {
      "Url": "replica-a.example.com"
    }
  ],
  "Id": "Raven/Replication/Destinations"
}
\end{lstlisting}

\subsubsection*{Partycjonowanie}

\par
Kolejnym aspektem związanym z działaniem w środowisku rozproszonym jest partycjonowanie danych pomiędzy różne węzły bazy danych. \textit{RavenDB} posiada również wsparcie dla tej funkcjonalności.
Podobnie jak w przypadku poprzednim, realizowana jest ona poprzez specjalną wtyczkę o nazwie \textit{Sharding Bundle} \cite{ravendb_sharding} \cite{ravendb_sharding_config}.

\par
Operacja partycjonowania bazy danych jest istotna z dwóch powodów. Po pierwsze, rozdzielenie danych może mieć pozytywny wpływ na szybkość działania całego systemu.
Zapytania nie są kierowane do jednego węzła, lecz ruch w sieci jest bardziej zrównoważony. Drugim powodem bardzo często jest zbyt duża ilość zgromadzonych danych.
Pojemność dysków jest ograniczona i biorąc pod uwagę wielkość bazy danych takich portali jak \textit{Facebook} \cite{hadoop_facebook_cluster_2}, wydaje się wręcz 
rzeczą niemożliwą, żeby taka ilość danych przechowywana była na jednym komputerze.

\par
Instalacja tej wtyczki jest praktycznie identyczna z instalacją poprzedniej wtyczki. Po pierwsze należy przekopiować odpowiedni plik z wtyczką do katalogu
zdefiniowanego w pliku konfiguracyjnym. Następnie należy zdefiniować odpowiedni dokument, mówiący bazie danych, w jaki sposób należy dokonać partycjonowania \cite{ravendb_sharding_config}.

\begin{lstlisting}[label=ravendb_config_sharding,caption=Przykładowa konfiguracja dokumentu partycjonowania]
{ // Raven/Sharding/ByUserName
  "Limits": [3],
  "Replica": 2
  "Definitions": [
    {
      "EntityName": "Users",
      "Paths": ["Username"]
    },
    {
      "EntityName": "Posts",
      "Paths": ["AuthorName"]
    }
  ]
}
\end{lstlisting}

W dokumencie tym definiujemy, jakie dokumenty będziemy chcieli partycjonować oraz jakim kluczem powinny być one rozróżniane.
Po wykonaniu tej operacji powinniśmy przystąpić do operacji definiowania, gdzie dane partycje powinny zostać zapisywane.

\begin{lstlisting}[label=ravendb_config_sharding_2,caption=Dalsza część konfiguracji partycjonowania]
{ "Id": "chunks/1", "Shards": ["http://shard1:8080", 
"http://shard1-backup:8080"], 
"Name": "ByUserName", "Range": ["aaa", "ddd"] }
{ "Id": "chunks/2", "Shards": ["http://shard1:8080", 
"http://shard2-backup:8080"], 
"Name": "ByUserName", "Range": ["ddd", "ggg"] }
{ "Id": "chunks/3", "Shards": ["http://shard2:8080", 
"http://shard3-backup:8080"], 
"Name": "ByUserName", "Range": ["ggg", "lll"] }
{ "Id": "chunks/4", "Shards": ["http://shard2:8080", 
"http://shard1-backup:8080"], 
"Name": "ByUserName", "Range": ["lll", "ppp"] }
{ "Id": "chunks/5", "Shards": ["http://shard3:8080", 
"http://shard2-backup:8080"], 
"Name": "ByUserName", "Range": ["ppp", "zzz"] }
{ "Id": "chunks/6", "Shards": ["http://shard3:8080", 
"http://shard3-backup:8080"], 
"Name": "ByUserName", "Range": ["000", "999"] }
\end{lstlisting}

Jak widać, w powyższym przykładzie zdefiniowanych jest sześć punktów podziału oraz sześć serwerów na które dane będą propagowane. 
Co ciekawe, przykład ten obrazuje również połączenie poprzedniej funkcjonalności z
partycjonowaniem. Pokazuje on w jaki sposób możemy podzielić każdy zbiór danych pomiędzy różne serwery oraz jednocześnie zwiększyć bezpieczeństwo przechowywanych danych poprzez 
replikację danych.

\par
Jeśli nasza baza danych jest podzielona za pomocą poprzednio omawianej wtyczki, praktycznie każde zapytanie o dokumenty rozdystrybuowane po różnych 
węzłach jest zadaniem typu \textit{Map/Reduce}. Jeśli na przykład tworzymy portal dla bloggerów, gdzie tabela użytkowników jest podzielona pomiędzy dwa serwery,
a my potrzebujemy znaleźć ilość użytkowników, którzy posiadają więcej niż dziesięć wpisów, musimy najpierw wykonać to zapytanie na dwóch węzłach bazy (krok \textit{Map})
natomiast następnie zsumować otrzymane wyniki (krok \textit{Reduce}).

\subsubsection {Podsumowanie}

\textit{RavenDB} posiada wiele cech wyróżniających go pośród baz danych \textit{NoSQL}. Po pierwsze, jest w całości stworzony przy pomocy technologii \textit{.NET}.
Po drugie posiada wsparcie dla transakcji. Model danych tej bazy, oparty na dokumentach, również bardzo dobrze współgra z obiektowym podejściem większości dzisiejszych języków
programowania.

\par
Bardzo ciekawym podejściem wydaje się być zastosowanie \textit{RESTful API} jako podstawowego interfejsu dostępowego. Daje to możliwość łatwej integracji nie tylko z 
językami opartymi na platformie \textit{.NET}, lecz z każdym, w którym możliwe jest wykonanie zapytania \textit{HTTP}.

\par
Projekt biblioteki klienckiej, oparty głównie na architekturze sprawdzonego rozwiązania, jakim jest \textit{NHibernate}, również okazał się być bardzo dobrym pomysłem.
Dzięki niemu jest ona znacznie przejrzystsza i zrozumiała, a co więcej korzysta z doświadczeń dużo bardziej sprawdzonego i przetestowanego rozwiązania.
Co więcej, zastosowanie wzorca \textit{Unit of work} znacznie upraszcza wiele operacji. Warto zauważyć, że w dobie rozwijającego się \textit{Entity Framework} oraz 
\textit{LINQ2SQL} implementacja własnego \textit{LINQ Providera} jest rzeczą bardzo istotną. Z tego względu dobrze, że \textit{RavenDB} jest wręcz stworzony w oparciu o tą technologię.

\par
\textit{RavenDB} posiada bardzo ciekawie zaprojektowany system wtyczek. Istnieje bardzo duży zbiór gotowych wtyczek rozszerzających standardowe działanie systemu.
W przypadku, gdy nie znajdziemy interesującej nas wtyczki, zawsze możemy spróbować stworzyć taką, która w pełni zrealizuje nasze potrzeby.

\par
\textit{RavenDB} bardzo dobrze radzi sobie w środowisku rozproszonym. Posiada wsparcie dla replikacji oraz partycjonowania danych.
Te dwie funkcjonalności są jednymi z najważniejszych w dzisiejszych systemach rozproszonych. Pozwalają one zwiększyć zarówno bezpieczeństwo systemu oraz poprawić jego wydajność.
Co więcej, zaimplementowanie w bibliotece klienckiej mechanizmu \textit{failover} znacznie upraszcza implementacje rozproszonych aplikacji oraz dodatnio wpływa na 
czas odpowiedzi całego systemu.

\par
\textit{RavenDB} jest bardzo dobrze zaprojektowaną oraz wykonaną bazą danych, która idealnie nadaje się do tworzenia dużych systemów, nastawionych głównie na szybkość
oraz bezpieczeństwo przechowywanych danych.



\subsection {Cassandra}

\textit{Cassandra} w odróżnieniu od \textit{RavenDB} jest bazą danych typu klucz-wartość. Została ona napisana w języku \textit{Java} na potrzeby portalu \textit{Facebook}.
Od roku 2008 została przekazana pod opiekę fundacji \textit{Apache} \cite{cassandra_intro}, jednak nadal jest wykorzystywana w \textit{Facebook}.

\par
\textit{Cassandra} łączy w sobie cechy dwóch najważniejszych baz danych \textit{NoSQL}, z punktu widzenia wkładu w rozwój tego zagadnienia: \textit{Google BigTable} oraz 
\textit{Amazon Dynamo}. Model danych tego systemu bazodanowego bazuje w dużej mierze na podejściu zaproponowanym przez \textit{Google BigTable}. Opera się on na uporządkowaniu
danych w postaci tabel zawierających klucz i wartość, przy czym wartością mogą być kolejne tabele. Sposób funkcjonowania w środowisku rozproszonym został natomiast zaczerpnięty
z bazy danych \textit{Amazon Dynamo}.

\par
\textit{Cassandra} została zaprojektowana z myślą o bardzo dużej wydajności oraz pracy w środowisku rozproszonym. Wspiera ona wykonywanie zadań \textit{Map/Reduce} przy pomocy
\textit{Hadoop}. W bardzo wydajny sposób radzi sobie z partycjonowaniem danych oraz ich replikacją na inne węzły bazy danych. Co najważniejsze, \textit{Cassandra}
została zaprojektowana zgodnie z zasadą braku pojedynczych punktów krytycznych systemu. W myśl niej system powinien być zaprojektowany w taki sposób,
aby awaria któregokolwiek jego elementu nie powodowała awarii całego systemu.

\subsubsection{Model danych}

\textit{Cassandra} jest to baza danych pozbawiona schematu, jaki jest znany z relacyjnych baz danych. Posiada on pewne podobieństwa, jednak w wielu kluczowych 
elementach się różni. Jest on również zorganizowany w postaci kolumnowej, jednak nie ma wymogu, żeby każdy wiersz posiadał takie same kolumny. Co więcej, wartościami kolumn mogą być również kolumny.
Kolumny oraz ich metadane mogą być w każdej chwili działania systemu zmieniane.

\par
Podstawowym elementem modelu danych tej bazy jest kolumna. Różni się ona znacznie od kolumny znanej z relacyjnych baz danych. W systemie \textit{Cassandra} jest to krotka
zawierająca trzy wartości.

\begin{enumerate}
	\item Identyfikator
	\item Wartość
	\item Stempel czasowy
\end{enumerate}

\par
Oprócz standardowej kolumny wyróżniono dodatkowo trzy specjalne rodzaje kolumn.

\begin{enumerate}
	\item \textit{Kolumna wygasająca} - Jest to specjalny typ kolumny, z którym związana jest wartość \textit{TTL}. Informuje ona system po upływie jakiego czasu
	należy daną kolumnę usunąć. Mechanizm ten działa dobrze dla wartości parametru \textit{TTL} rzędu sekund, gdyż w przypadku mniejszych wartości, synchronizacja
	tych kolumn wiązałaby się z dużym narzutem czasowym na sprawdzanie danych oraz synchronizację pomiędzy węzłami w klastrze. Kolumna taka może stanowić dobry nośnik
	danych, których czas życia jest ograniczony, jak na przykład flaga dotycząca tego, czy użytkownik jest zalogowany lub ziarna sesji.
	
	\item \textit{Kolumna zliczająca} - Jest ona w stanie zliczać w sposób jednostkowy ilość wystąpień pewnych zdarzeń w systemie, jak na przykład ilość wyświetleń danej strony.
	Baza danych umożliwia jedynie modyfikację tej kolumny w sposób inkrementalny lub dekrementalny, nie jest możliwe ustawienie \textit{explicite} wartości tego pola. Ten typ kolumny 
	nadaje się bardzo dobrze w przypadku projektowania bazy danych dla aplikacji społecznościowych, do zliczania ilości zalogowanych użytkowników.
	
	\item \textit{Super kolumna} - Jest to jeden z najpopularniej stosowanych specjalnych typów kolumn. Cechuje się tym, że jego wartościami mogą być inne kolumny, w szczególności inne super kolumny. 
	Dzięki temu możliwe jest tworzenie wielowymiarowych struktur danych.
	
	
\end{enumerate}

\par
Elementem agregującym kolumny jest rodzina kolumn. W przybliżeniu można ją porównać do tabeli z relacyjnego schematu danych. Każda rodzina kolumn może zawierać dowolną liczbę kolumn,
pod warunkiem, że nie przekracza ona dwóch miliardów \cite{cassandra_limitations}. Istnieje również ograniczenie co do wielkości danych przechowywanych w kolumnach i wynosi ono \textit{2GB}.
Biorąc pod uwagę, że nie powinno się w bazie danych przechowywać wartości większych niż parę \textit{MB}, ograniczenie to nie wpływa negatywnie na możliwości wykorzystania systemu \textit{Cassandra}.

\par
Kolejnym bardzo istotnym elementem modelu danych systemu \textit{Cassandra} są przestrzenie kluczy. Można je porównać do oddzielnych baz danych w obrębie jednego silnika bazodanowego.
Stanowią one pewien pojemnik, w którym tworzone są rodziny kolumn. Co więcej, mechanizm replikacji danych działa w obrębie tej samej przestrzeni kluczy.

\par
W tradycyjnej, relacyjnej bazie danych, każda kolumna posiada określony typ. Z tego względu w kolumnie zawierającej jedynie liczby całkowite nie można zapisać danych tekstowych. 
W systemie \textit{Cassandra} nie istnieje pojęcie statycznego schematu.
Każda kolumna składa się jedynie z trzech wartości: klucza, wartości właściwej oraz stempla czasowego. Jednak podobnie jak w relacyjnych bazach danych są one mocno typizowane.
Typ danych wartości przechowywanej w kolumnie lub typ klucza dla kolumny nosi nazwę walidatora. Typ danych nazwy kolumny nosi nazwę komparatora. Zgodnie z zasadą powinno się je podawać podczas tworzenia 
kolumn, jednak nie jest to wymagane, gdyż domyślnym typem jest ciąg binarny. 

\par
\textit{Cassandra} posiada wszystkie najpopularniejsze typy danych, takie jak  liczba naturalna \textit{int}, wartość binarna \textit{boolean}, ciąg binarny \textit{blob} 
czy unikalny identyfikator \textit{uuid}. Dostarcza również swoich własnych unikalnych typów danych jak \textit{counter}, który jest stosowany w kolumnach zliczających. 

\par
Dodatkowo istnieje możliwość zastosowania kompresji rodzin kolumn. Dzięki temu możemy zaoszczędzić bardzo dużo miejsca, jeśli nasze dane w pewien sposób powielają się w obrębie bazy danych.
Zgodnie z danymi firmy \textit{DataStax}, zgromadzonymi w dokumencie \cite{datastax_cassandra}, kompresja może zwiększyć ogólną wydajność naszej bazy danych nawet o $ 10\% $. Co więcej, gdy 
redukcja wielkości bazy danych jest dwu lub czterokrotna, otrzymujemy $ 25\% - 35\% $ przyrost szybkości odczytu oraz $ 5\% - 10\% $ przyrost szybkości zapisu.

\par
\textit{Cassandra} wspiera w swoim modelu danych indeksy. Dzięki ich zastosowaniu można znacznie zwiększyć wydajność wyszukiwania oraz sortowania danych.
Wyróżniamy dwa rodzaje indeksów w bazie danych \textit{Cassandra}

\begin{enumerate}
	\item \textit{Indeksy główne} - Każda rodzina kolumn w bazie danych posiada główny indeks, obejmujący wartości kluczy kolumn. Tworzony jest on domyślnie przez system bazy danych,
	każdy z węzłów klastra utrzymuje jego spójność w swoim obrębie.
	
	\item \textit{Indeksy pochodne} - Indeksy te można tworzyć na wartościach danych kolumn. Należy je stworzyć \textit{explicite}. Znajdują one zastosowanie w sytuacji, gdy chcemy 
	wyszukać lub przefiltrować dane w rodzinie kolumn, nie używając do tego wartości klucza, lecz wartości kolumny. W relacyjnej bazie danych, pomimo małej wydajności takiego rozwiązania,
	jesteśmy w stanie jako predykat zapytania umieścić dowolną kolumnę tabeli. W celu uzyskania tego samego efektu w systemie \textit{Cassandra} należy stworzyć indeks pochodny na wartości,
	którą chcemy odfiltrować.
	
\end{enumerate}

\par
Jeśli projektujemy bazę danych opartą na systemie \textit{Cassandra}, należy zwrócić uwagę na kilka podstawowych kwestii. Po pierwsze należy pomyśleć najpierw o zapytaniach jakie będą wykonywane
na bazie danych, a dopiero później o strukturze kolumn oraz rodzin kolumn. Jest to podejście odwrotne do tego znanego z zarządzania relacyjnymi bazami danych, 
gdzie zazwyczaj najpierw się myśli o tabelach, następnie o zapytaniach, a ostateczną optymalizację dokonuje się poprzez tworzenie indeksów na odpowiednich tabelach. Model danych systemu 
\textit{Cassandra} w inny sposób traktuje indeksy niż relacyjne bazy danych. Częstą praktyką jest tworzenie specjalnych kolumn, których zadaniem jest jedynie filtrowanie pewnych danych.

\par
Kolejnym ważnym aspektem jest denormalizacja. W celu osiągnięcia większej prędkości wyszukiwania w bazie danych, bardzo częstą praktyką jest denormalizacja schematu.
Utrudnia to zapis danych, jednak znacznie przyspiesza operację wyszukiwania oraz odczytu. Dodatkowo w systemie \textit{Cassandra} nie występuje operacja \textit{JOIN}, przez co utrzymywanie
bazy danych w postaci znormalizowanej, nie przełożyłoby się w sposób pozytywny na przyrost szybkości działania bazy.

\par
Co więcej, należy pamiętać o tym, że w przeciwieństwie do \textit{RavenDB}, \textit{Cassandra} nie wspiera zasady \textit{ACID} w rozumieniu występowania transakcji.
Należy samemu dbać o spójność danych po wystąpieniu błędnego zapisu do bazy. Brak transakcji podyktowany jest naciskiem, jaki został położony na wydajność tej bazy danych,
która ze względu na swoje pierwotne zastosowanie była znacznie bardziej istotna niż spójność przechowywanych w niej danych.


\subsubsection {Architektura}

Jak już zostało zaznaczone na wstępie, \textit{Cassandra} w dużej mierze czerpie z baz danych \textit{Google BigTable} oraz \textit{Amazon Dynamo}.
Model danych z drobnymi zmianami został przeniesiony z bazy danych \textit{Google}, natomiast mechanizmy funkcjonowania w środowisku rozproszonym z \textit{Dynamo}.

\par
Ze względu na implementacje w oparciu o język \textit{JAVA}, \textit{Cassandra} jest w pełni przenośna pomiędzy różnymi systemami operacyjnymi.
Instalacja tego oprogramowania w najprostszym przypadku ogranicza się do dwóch aspektów:

\begin{enumerate}
\item Pobrania odpowiedniego środowiska uruchomieniowego platformy \textit{JAVA}
\item Pobrania oraz rozpakowania najnowszej wersji programu \textit{Cassandra} oraz uruchomienia 
	\begin{itemize}
		\item dla systemu \textit{Windows} skryptu \textit{cassandra.bat} 
		\item dla systemu \textit{Linux} skryptu \textit{cassandra}		
	\end{itemize}
\end{enumerate}

\par
O bazie danych \textit{Cassandra} należy myśleć jak o rozproszonym zbiorze niezależnych węzłów klastra. Każdy z nich funkcjonuje na zasadzie \textit{peer-to-peer},
dzięki czemu brak jest wąskich gardeł w tym systemie. Dowolny węzeł klastra może przestać odpowiadać na żądania, co nie zakłóci działania całego systemu.

\par
W systemie \textit{Cassandra} nie ma wyróżnionych węzłów zajmujących się domyślnie koordynacją pracy systemu. Z tego względu klient może podłączyć się do dowolnego węzła
bazy danych i wykonywać operacje dotyczące całej bazy danych. Węzeł taki staje się w tym momencie koordynatorem pomiędzy pojedynczym zapytaniem klienta a resztą bazy danych.

\par
Podczas żądania zapisu danych do systemu \textit{Cassandra}, węzeł będący chwilowym koordynatorem operacji stara się zapisać nowe dane do wszystkich węzłów, 
które przechowują te dane lub ich kopie replikacyjne. Bardzo istotnym parametrem w tym procesie jest współczynnik spójności danych $k$. Po wykonaniu operacji zapisu danych
węzeł koordynujący czeka na $k$ odpowiedzi od węzłów, na które starał się zapisać dane. Jeśli je otrzyma, klient dostaje powiadomienie o sukcesie operacji. Jak łatwo zauważyć,
może to prowadzić do sytuacji, w której przy próbie zapisu do trzech węzłów jedynie dwa odpowiedzą poprawnym zapisem. Przy założeniu współczynnika $k = 2$ węzeł koordynujący odpowie
komunikatem sygnalizującym poprawny zapis, jednak dane w węźle trzecim mogą być niespójne. Sytuację taką można naprawić poprzez zastosowanie specjalnego narzędzia \textit{nodetool},
które nadpisują niespójne dane wartościami z innych węzłów klastra. Warto zauważyć, że system nie uruchomi go automatycznie, a węzeł z niespójnymi danymi nie może brać udziału w funkcjonowaniu systemu.

\par
Operacja odczytu danych z bazy danych \textit{Cassandra} jest zbliżona do operacji zapisu. Węzeł, do którego aktualnie klient jest podłączony, staje się koordynatorem całej operacji.
Dane odczytywane są również niezależnie z różnych węzłów klastra posiadających repliki danych. W przypadku wykrycia braku spójności danych, klientowi przekazywane są dane oznaczone najświeższym
stemplem czasowym, natomiast dane niespójne są naprawiane w tle.

\subsubsection*{Protokół \textit{Gossip}}

\par
W celu identyfikacji oraz diagnostyki węzłów klastra, postanowiono w tym systemie zaimplementować protokół \textit{Gossip}. Jest to typ protokołu 
opartego na założeniach sieci \textit{peer-to-peer}, w której każdy z uczestników co jakiś czas wymienia się informacjami na swój temat. W szczególności
o tym czy dany węzeł klastra działa oraz czy działa wydajnie. Został on opisany dokładnie w pracy \cite{gossip}. Bardzo istotnym elementem tego protokołu jest zdecentralizowana
wiedza na temat węzłów sieci. Każdy z nich posiada własną listę węzłów, z którymi powinien się komunikować.

\par
Na podstawie danych czerpanych z \textit{Gossip}, węzły klastra nie kierują swoich żądań do węzłów, o których wiedzą, że są nieosiągalne lub mogą odpowiadać z dużym opóźnieniem.
Co ciekawe, każdy węzeł bazy danych wylicza na podstawie specjalnego algorytmu próg czasowy, po którym uznaje, że odpytywany węzeł jest nieosiągalny.
Bierze on pod uwagę dane historyczne, dotyczące odpowiedzi badanego węzła w postaci średniej kroczącej oraz obciążenie i konfigurację sieci.

\subsubsection*{Naprawianie uszkodzonego węzła}

\par
Awaria węzła w klastrze może być spowodowana między innymi awarią sprzętu lub błędem oprogramowania, działającego na tej maszynie. Warto zauważyć, że ma ona bardzo często 
charakter przejściowy oraz rzadko się zdarza, aby awaria była tak poważna, że wymagana jest całkowita wymiana komputera. Ponieważ węzły klastra odpytują w ramach protokołu \textit{Gossip}
inne węzły, nawet jeśli na podstawie zgromadzonych danych wydają się one być niedziałające. Z tego względu, jeśli węzeł zostanie naprawiony, od razu może wznowić pracę.
Warto zauważyć jednak, że elementem, który najczęściej ulega uszkodzeniu w systemach komputerowych jest dysk twardy. Jego wymiana może jednak odbyć się bez większych przerw czasowych w działaniu serwera.
Dzisiejsze technologie dysków twardych, takie jak \textit{SATA} oraz \textit{SAS}, wykorzystywane w systemach serwerowych umożliwiają wymianę wadliwego sprzętu nawet bez wyłączania maszyny 
\cite{sata_spec}.

\par
Jeśli dany węzeł stanie się operacyjny po dłuższym czasie przerwy w działaniu, najprawdopodobniej posiada on niespójne lub przedawnione dane.
Tyczy się to zarówno danych operacyjnych oraz danych pochodzących z procesu replikacji. Jeśli dany węzeł zostanie oznaczony jako niedziałający, wszystkie dane, które powinny
być na niego zreplikowane zostają zapisane na innych węzłach. Dzięki takiemu zabiegowi można w bardzo szybki sposób przywrócić spójność danych na naprawionym węźle.
Podejście to pomimo swojej szybkości ma jedną bardzo istotną wadę. Od momentu faktycznej awarii węzła, do czasu jej wykrycia mija zawsze pewien czas, podczas którego do węzła
wysyłane są pewne zapytania. Są one tracone bez zapisania ich na innych węzłach sieci. Z tego względu zaleca się, aby periodycznie uruchamiane było narzędzie \textit{nodetool} służące do 
zarządzania węzłami z parametrem \textit{repair}. Naprawia ono spójność danych na wszystkich węzłach, nawet jeśli część z nich została utracona w opisanym procesie.
Narzędzie to powinno być uruchamiane przez skrypty, stworzone przed administratorów systemu. W zależności od obciążenia i awaryjności systemu.

\par
W systemie \textit{Cassandra} każdy węzeł co sekundę wymienia informacje z dowolnymi trzema węzłami na swój temat oraz na temat węzłów, o których posiada informację.
Dzięki takiemu zabiegowi znacznie zredukowana została ilość zapytań do węzłów sieci. Oprócz wiadomości na temat stanu poszczególnych węzłów, każdy pakiet tego protokołu
posiada wersję. Dzięki temu, jeśli jeden z węzłów podczas wymiany informacji otrzyma od dwóch węzłów sprzeczne informacje na temat trzeciego, może w prosty sposób zweryfikować,
która z nich jest aktualna.

\subsubsection*{Konfiguracja węzłów}

\par
Indywidualna konfiguracja każdego węzła decyduje o tym jaką jest on częścią klastra oraz jakie są jego zadania. Podczas startu każdego nowego węzła
dokonuje on sprawdzenia, jaka jest nazwa klastra, w którym będzie pracować oraz które z węzłów są oznaczone jako \textit{seeds}. Lista tych węzłów jest przechowywana w pliku
\textit{cassandra.yaml}, znajdującym się na każdym węźle. Ze względu na spójność protokołu \textit{Gossip}, ważne jest aby była identyczna dla każdego z nich.
Węzły te są pierwszymi, z którymi inne węzły komunikują się podczas wymiany informacji w protokole \textit{Gossip}. Ich zadanie ogranicza się jedynie do rozpoczęcia wymiany informacji
w tym protokole.

\par
Kolejnym aspektem na jaki należy zwrócić uwagę podczas konfiguracji klastra są specjalne identyfikatory każdego z nich. Mówią one o tym jakie dane są przechowywane na wybranym węźle.
Dzięki wiedzy o swoim identyfikatorze oraz identyfikatorach innych węzłów, każdy z nich może w prosty sposób zlokalizować część danych potrzebną do pracy.
Ma to szczególne znaczenie w zagadnieniu partycjonowania danych pomiędzy różne węzły klastra. Istotne jest, aby konfiguracja identyfikatorów została dokonana przed uruchomieniem klastra.

\subsubsection*{Partycjonowanie}

\par
\textit{Cassandra} została zaprojektowana z myślą o wbudowanym wsparciu dla partycjonowania oraz redundancji danych. Mechanizm partycjonowania danych jest w pełni konfigurowany przez
specjalne obiekty znoszące nazwę \textit{partitioner}. Są to specjalne klasy języka \textit{JAVA}, które odpowiadają za strategię dystrybucji danych na różne węzły sieci.
W systemie \textit{Cassandra} o całym zbiorze danych należy myśleć jako o pewnego rodzaju kole. Węzły posiadające pewien podzbiór danych, reprezentowane są poprzez wycinki tego koła o powierzchni
proporcjonalnej do ilości przechowywanych danych. 

\par
Jak już zostało wspomniane wcześniej, każdy z węzłów posiada pewien identyfikator związany z częścią danych, jakie posiada. Ponieważ model danych systemu \textit{Cassandra} jest zorganizowany
w postaci elementów \textit{klucz - wartość}, podczas partycjonowania dane dzielone są przy użycia klucza każdej kolumny. Jeśli do bazy danych wysłane zostanie zapytanie o dane identyfikowane 
pewnym kluczem, algorytm ich wyszukiwania zaczyna od węzła o najmniejszej wielkości identyfikatora, a następnie, zgodnie z ich rosnącymi wartościami, wyszukuje poprzednik pierwszego węzła o wartości klucza
większej niż wyszukiwanych danych. 

\par
Pewna modyfikacja tego algorytmu jest wykorzystywana przy wyszukiwaniu danych w sytuacji, gdy dane rozproszone są pomiędzy różne węzły różnych klastrów. W tym przypadku węzły są wyszukiwane 
w ten sam sposób, jednak po osiągnięciu węzła końcowego jednego klastra, algorytm zaczyna wyszukiwać w kolejnym klastrze zaczynając od węzła o najmniejszej wartości identyfikatora.
Najważniejsze w tym podejściu jest to aby żadne wycinki koła danych nie nakładały się na siebie w obrębie całej infrastruktury.

\par
Istnieje kilka rodzajów wbudowanych w system \textit{Cassandra} algorytmów partycjonowania danych. Warto jednak zwrócić uwagę, że wybór odpowiedniego sposobu podziału musi być 
dokonany na początku działania całego systemu, gdyż nie ma możliwości zmiany go bez wyłączania całego systemu.

\begin{itemize}
	\item Pierwszym z wbudowanych algorytmów podziału jest \textit{RandomPartitioner}. Jest on domyślną strategią oraz jest optymalny dla większości zastosowań.
	Idea jego działania jest bardzo prosta, przez co niezwykle wydajna. Cały algorytm opiera się na wyliczeniu funkcji skrótu \textit{MD5} z klucza. Jak wiadomo \textit{MD5} może przyjmować 
	$2^{128}$ wartości \cite{md5_rfc}. Cały ten przedział jest dzielony na tyle równolicznych podprzedziałów, ile jest węzłów w sieci. W przypadku, gdy system otrzymuje żądanie odczytu danych
	identyfikowanych pewnym kluczem, w pierwszym kroku obliczana jest wartość funkcji skrótu dla niego, a następnie, przy pomocy opisanego wcześniej algorytmu, wyszukiwany jest odpowiedni węzeł sieci.
	Ze względu na fakt, że \textit{MD5} daje wartości podlegające w przybliżeniu rozkładowi jednorodnemu, dane są równomiernie rozdystrybuowane po wszystkich węzłach sieci.
	
	\item Kolejny algorytm podziału danych opiera się na partycjonowaniu według posortowanych wartości klucza każdego wiersza. Dzięki temu w każdym węźle dane są posortowane.
	Algorytm ten wydaje się być bardzo przydatny jeśli chcemy wykonywać jakieś zapytania opierające się na wyszukiwaniu w danych posortowanych. 
	Nie jest on jednak zalecany przez firmę \textit{DataStax}, z następujących względów \cite{datastax_cassandra}
	
	\begin{itemize}	
		\item W przypadku, gdy dane są grupowo zmieniane lub wykonywane są zapytania do danych o bliskich wartościach klucza, wszystkie operacje są wykonywane na jednym węźle klastra,
		znacznie zwiększając jego obciążenie i wydłużając czas odpowiedzi systemu.
		
		\item Rozwiązanie to wymaga od administratorów oraz architektów systemu ręcznego podziału przestrzeni kluczy pomiędzy węzły w klastrze. Jest to bardzo trudne zadanie, gdyż wymaga
		dokładnej estymacji histogramu takiego rozkładu, co w wielu przypadkach jest wręcz niemożliwe.
		
		\item Istnieje bardzo duże prawdopodobieństwo nierównomiernego rozłożenia się danych w klastrze, głównie ze względu na niskie prawdopodobieństwo istnienia takiej samej dystrybucji
		ilości danych w obrębie jednej rodziny kolumn.		
	\end{itemize}
	
	Istnieją trzy wbudowane algorytmy, realizujące uporządkowane partycjonowanie danych.
	
	\begin{itemize}
		\item \textit{ByteOrderedPartitioner} - Podczas dokonywania porównania, dane są konwertowane do postaci binarnej oraz analizowana jest ich bitowa reprezentacja.
		W tym algorytmie nie jest brana pod uwagę semantyka danych, nawet jeśli klucz ma wartość tekstową, jest on konwertowany do ciągu bajtowego, a następnie porównywany z innymi.
		
		\item \textit{OrderPreservingPartitioner} - Klucze w tym algorytmie muszą być kodowane jako \textit{UTF-8}, a następnie na podstawie tej reprezentacji dokonywane jest porównanie.
		
		\item \textit{CollatingOrderPreservingPartitioner} - Działa podobnie do poprzedniego, z tą różnicą, że klucze są porównywane nie na podstawie ich zapisu w \textit{UTF-8},
		tylko zgodnie z zasadami angielskiego porządku alfabetycznego.
	\end{itemize}
\end{itemize}

\subsubsection*{Replikacja}

\par
Kolejnym bardzo ważnym zagadnieniem, z punktu widzenia funkcjonowania bazy danych \textit{Cassandra}, jest replikacja danych. Jest to proces polegający na powielaniu zbiorów danych pomiędzy
węzły klastra. Zwiększa on znacznie bezpieczeństwo danych, gdyż w przypadku awarii jednego z węzłów klastra, zawsze istnieje kopia jego danych na jakimś innym węźle.
Wybór algorytmu replikacji oraz jego ustawień dokonywany jest już podczas tworzenia przestrzeni kluczy. Najważniejszym parametrem dla tego procesu jest współczynnik replikacji.
Liczba ta określa, w ilu niezależnych lokacjach mają znaleźć się dane przechowywane w klastrze.

\par
Podobnie jak w przypadku partycjonowania danych istnieje wiele wbudowanych algorytmów replikacji danych.

\begin{itemize}
	\item \textit{SimpleStrategy} - Jest to domyślna oraz najprostsza strategia. Jeśli na węźle $k$ znajdują się pewne dane, to zgodnie z tym algorytmem zostaną one zwielokrotnione
	na węzły $k+1, k+2, ... , k+f$, gdzie $f$ jest współczynnikiem replikacji. Jak widać wykorzystuje on wiedzę czerpaną z algorytmu partycjonowania danych.
	
	\item \textit{NetworkTopologyStrategy} - Jest on znacznie bardziej zaawansowanym algorytmem niż poprzedni, uwzględnia architekturę oraz topologię klastra komputerowego.
	Dzięki temu jest w stanie tworzyć kopie pomiędzy węzłami, które najszybciej ze sobą współpracują lub rozdzielać zbiory kopii bezpieczeństwa pomiędzy różne klastry komputerowe.
	Jest on rekomendowany w przypadku posiadania bardzo dużego systemu komputerowego, dla którego czas odpowiedzi jest elementem krytycznym. 
	Algorytm ten otrzymuje informacje na temat architektury sieci dzięki pomocy specjalnych modułów, zwanych \textit{snitch}. Starają się one, na podstawie takich danych jak adres \textit{IP} komputera,
	lub plików konfiguracyjnych, określić lokalizację węzła, na którym działają w obrębie całego systemu. W celu poprawienia wydajności klastrów bazy danych 
	\textit{Cassandra} w środowisku chmury \textit{Amazon}, zdecydowano się stworzyć specjalny \textit{snitch}, który jest zoptymalizowany pod usługę \textit{EC2}.
\end{itemize}

\subsubsection {Biblioteki klienckie}

\textit{Cassandra} posiada bardzo bogatą ilość narzędzi dostępowych. Zostało również napisanych wiele bibliotek języków wysokiego poziomu, dzięki którym 
istnieje możliwość łatwego oraz szybkiego łączenia się z bazą danych w aplikacjach napisanych w takich językach jak \textit{PHP}, \textit{JAVA} oraz \textit{PYTHON}.

\par
Pierwszym oraz najważniejszym ze względów historycznych sposobem łączenia się z bazą danych \textit{Cassandra} jest \textit{Thrift API}. Jest to biblioteka, 
dzięki której możemy, w prosty sposób, zdalnie wywoływać procedury pomiędzy programami napisanymi w różnych językach, takich jak \textit{C++}, \textit{JAVA}, \textit{Erlang}
czy na przykład \textit{JavaScript} \cite{thrift_overview}.

\par
Na jej potrzeby stworzony został pewien metajęzyk opisujący serwisy oraz dane wymieniane pomiędzy partycypantami protokołu.

\begin{lstlisting}[label=thrift_sample,caption=Przykład definicji zdalnych metod]
struct User {
	1: i32 id,
	2: string login
	3: string password
}

service UserManager {
	i32 authenticate(1: User user),
	User getUserById(1: u32 id)
}
\end{lstlisting}

Przykład zaprezentowany na listingu \ref{thrift_sample} definiuje jedną strukturę, opisującą użytkownika oraz jeden serwis, zajmujący się zarządzaniem użytkownikami poprzez ich autoryzacje oraz 
pobieranie danych o nich. Jak łatwo zauważyć, język ten jest bardzo podobny składniowo do \textit{C}.

\par
Na bazie protokołu \textit{Thrift} zostało stworzonych wiele bibliotek wysokiego poziomu, ułatwiających prace z bazą danych \textit{Cassandra}. 
Jego wykorzystanie w tym obszarze szybko zaczęło jednak dostarczać pewnych problemów \cite{datastax_cassandra}. Przede wszystkim, protokół ten jest bardzo nisko poziomowy, co zaczęło 
generować duże problemy przy wprowadzaniu wsparcia dla najnowszych wersji baz danych pośród wielu bibliotek klienckich, napisanych w różnych językach. Ostatecznie wiele z tych narzędzi 
przestało poprawnie funkcjonować. Z tego względu powoli zaczęto odchodzić od tego sposobu dostępu bo bazy danych na rzecz nowego, opartego na języku bardzo podobnym do \textit{SQL}, o nazwie
\textit{CQL}.

\par
\textit{CQL} jest to imperatywny język programowania, oparty w dużej mierze na języku \textit{SQL}. Został on wprowadzony do systemu \textit{Cassandra} w wersji \textit{0.8} i 
od tamtego czasu obserwuje się jego szybki rozwój. Jego aktualna wersja, opatrzona numerem\textit{2.0}, wprowadziła wiele usprawnień dla niektórych komend oraz jest kompatybilna 
z wydaniem \textit{1.0} systemu \textit{Cassandra}

\par
\textit{CQL} umożliwia  zarówno modyfikację struktury bazy danych, jak również operacje na samych danych. Posiada on wiele mechanizmów znanych z języka 
\textit{SQL}, jak na przykład klauzulę \textit{SELECT} lub \textit{INSERT}. Warto zauważyć, że ich zastosowanie nie różni się praktycznie od ich odpowiednika z relacyjnych baz danych.

\begin{lstlisting}[label=cql_basic,caption=Przykładowe polecenia języka \textit{CQL}]
INSERT INTO users (KEY, login) 
	VALUES('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6', 'user1')
SELECT * FROM user WHERE KEY IN (
	'cfd66ccc-d857-4e90-b1e5-df98a3d40cd6', 
	'dfd67ccc-d857-b1e5-4e90-df98a3d40cd6'
)
\end{lstlisting}

Przykłady zaprezentowane na listingu \ref{cql_basic} uruchomiłyby się również w środowisku \textit{MSSQL} oraz \textit{ORACLE}. Warto zauważyć, że jedyną różnicą pomiędzy \textit{CQL} a \textit{SQL} jest
część odpowiadająca za \textit{DDL} (\textit{Data Definition Language}). Ponieważ w systemie \textit{Cassandra} nie istnieją tabele, indeksy oraz klucze takie same jak w relacyjnych bazach danych,
brak jest poleceń manipulujących nich strukturą. Zamiast tego istnieją polecenia pozwalające na tworzenie przestrzeni kluczy oraz rodzin kolumn. W zakresie manipulacji danymi można przyjąć, że \textit{CQL}
jest niepełnym dialektem języka \textit{SQL}.

\par
\textit{Cassandra} posiada również narzędzie umożliwiające interaktywne połączenie z bazą danych oraz dokonywanie modyfikacji zarówno struktury bazy danych jak i samych danych w niej 
zawartych. Nazywa się ono \textit{Cassandra-cli} i chociaż nie jest przeznaczone do dostępu do bazy danych w warunkach produkcyjnych, jest bardzo użyteczne podczas nauki,
projektowania oraz testowania i diagnostyki bazy danych.

\par
Ostatnią grupę narzędzi dostępowych stanowią biblioteki klienckie. Jak już zostało wspomniane wcześniej, \textit{Cassandra} posiada ich bardzo wiele, napisanych w 
praktycznie każdym ważniejszym języku programowania.

\par
Pierwszą oraz najważniejszą z nich jest \textit{Hector}. Jest to biblioteka stworzona w oparciu o język \textit{JAVA}. Dostarcza wielu usprawnień, których brakuje podczas 
natywnego korzystania z \textit{Thrift API}, jak na przykład wielokrotne wykorzystywanie istniejących połączeń, integrację z \textit{JMX} oraz mechanizm \textit{failover}.
Dodatkowo posiada bardzo duże możliwości konfiguracji poziomu logowania, co niewątpliwie przydaje się podczas rozwiązywania problemów związanych z wydajnością oraz ewentualnymi
błędami bazy danych. Zaimplementowano w niej, jako pierwszej bibliotece klienckiej wsparcie dla języka \textit{CQL}.

\par
Kolejną biblioteką jest \textit{Phpcassa}. Nie jest ona tak zaawansowana jak \textit{Hector}, posiada jednak wsparcie dla wykorzystywania istniejących połączeń oraz wsparcie dla 
indeksów wtórnych.

\subsubsection {Podsumowanie}

\textit{Cassandra} jest to bardzo dobrze zaprojektowana oraz wykonana baza danych typu \textit{NoSQL}. Posiada ona bardzo ciekawy model danych oraz rozbudowany model 
funkcjonowania w środowisku rozproszonym, który w przeciwieństwie do \textit{RavenDB} jest wbudowany w istotę jej architektury.

\par
Model danych oparty jest na zbiorach typu \textit{klucz-wartość}, znanych z bazy danych \textit{Google BigTable}. Chociaż może się wydawać bardzo podobny do relacyjnego modelu
danych, posiada w sobie dość istotne różnice. Jedną z nich jest brak operacji \textit{JOIN} oraz pojęcia klucza obcego. Z tego względu, podczas projektowania baz danych w systemie 
\textit{Cassandra}, powinno zwracać się uwagę na inne aspekty oraz stosować się do innych zasad. Na przykład zaleca się, aby baza danych była zdenormalizowana. 
Dzięki temu uzyskujemy znaczne zwiększenie wydajności.

\par
\textit{Cassandra} posiada pewien język zapytań bardzo podobny w swojej naturze do języka \textit{SQL}. Umożliwia on dokonywanie zmian zarówno organizacji danych, jak również samych danych
zgromadzonych w bazie. Jest on bardzo szybko rozwijany, jego najnowsza wersja opatrzona jest numerem \textit{2.0}.

\par
Istnieje bardzo duża ilość bibliotek klienckich, dzięki którym w prosty oraz szybki sposób możemy stworzyć aplikację wykorzystującą system \textit{Cassandra}, w większości
największych języków programowania, takich jak \textit{JAVA} oraz \textit{PHP}.

\par
Pomimo tego, że \textit{Cassandra} nie wspiera transakcji w myśl zasady \textit{ACID}, to jednak posiada ona wiele mechanizmów zapewniających spójność danych już zapisanych w bazie.
Oznacza to, że jeśli podczas zapisu danych wystąpi pewien błąd to baza danych nie gwarantuje ich spójności. Jeśli jednak wszystkie operacje zapisu przebiegną poprawnie, to dane 
umieszczone w bazie pozostaną spójne.

\par
W systemie \textit{Cassandra} położono bardzo duży nacisk na funkcjonowanie w środowisku rozproszonym. Z tego względu posiada ona wsparcie dla algorytmów partycjonowania 
oraz replikacji danych. Co więcej, mechanizmy te są w pełni konfigurowalne. Można stworzyć własne algorytmy, odpowiadające za podział oraz strategię replikacji danych.


\subsection {MongoDB}

\textit{MongoDB}, podobnie jak \textit{RavenDB}, jest bazą danych \textit{NoSQL} typu dokumentowego. Jest to produkt \textit{Open Source}, jednak 
posiada on również wsparcie komercyjne \cite{mongodb_licensing}. Został on w całości stworzony w oparciu o \textit{C++}, dzięki czemu jest w pełni
przenośny pomiędzy platformami \cite{mongodb_cpp}. Ze strony producenta można pobrać jego wersje zarówno \textit{64} jak i \textit{32} bitową na
platformy \textit{Linux}, \textit{Windows}, \textit{OS X} oraz \textit{Solaris} \cite{mongodb_downloads}.

\par
Dane w systemie \textit{MongoDB} zorganizowane są, podobnie jak w przypadku \textit{RavenDB}, w postaci dokumentów. Są one również zapisywane w 
formacie pochodnym do \textit{JSON}, o nazwie \textit{BSON}. Jest to binarny standard zapisywania dokumentów \textit{JSON}, którego dokładny opis
znajduje się w pracy \cite{bson_spec}. Istnieje również pojęcie kolekcji dokumentów, jednak, podobnie jak w przypadku \textit{RavenDB}, spójność
struktury dokumentów w obrębie jednej kolekcji nie jest wymagana.

\par
Omawiana baza danych, podobnie jak poprzednie, posiada również wsparcie dla mechanizmu indeksowania. Można utworzyć indeks na dowolnym atrybucie 
dokumentu, należy jednak pamiętać wtedy, aby każdy dokument w kolekcji posiadał dany atrybut. Dzięki tej funkcjonalności wyszukiwanie danych
w bazie \textit{MongoDB} ulega znacznemu przyspieszeniu. Warto zauważyć, że mechanizm indeksów w omawianym systemie w dużym stopniu przypomina
ten znany z relacyjnych baz danych. Dzięki temu, programiści przyzwyczajeni do pracy z systemami takimi jak \textit{MSSQL}, na pewno w szybkim czasie
będą w stanie pracować z indeksami w \textit{MongoDB}.

\par
\textit{MongoDB}, podobnie jak obydwie omawiane wcześniej bazy danych, posiada wsparcie dla mechanizmu replikacji danych. Może on być wykorzystywany 
zarówno jako narzędzie zwiększające dostępność danych jak i bezpieczeństwo ich przechowywania. Replikacja w tym systemie odbywa się w sposób 
asynchroniczny. 

\par
\textit{MongoDB} posiada bardzo rozbudowany mechanizm automatycznego partycjonowania danych. Podobnie jak w systemie \textit{Cassandra}, pozbawiony
on jest wąskich gardeł oraz pojedynczych elementów, bez których system nie może funkcjonować. Zostały w nim zaimplementowane algorytmy zapewniające
równomierne rozłożenie danych po całym klastrze, jak również gwarantujące możliwość dodania kolejnego węzła bez przerw w działaniu systemu.

\par
Jedną z najważniejszych funkcjonalności, jakie musi posiadać baza danych, jest możliwość wyszukiwania interesujących nas informacji oraz 
filtrowania wyników zapytań. \textit{MongoDB} posiada bogaty mechanizm formułowania zapytań, bardzo podobny w swojej strukturze do funkcyjnej składni
\textit{LINQ}, znanej z produktu \textit{RavenDB}. Wiele zapytań z języka \textit{SQL} w bardzo prosty sposób daje się przełożyć na system wyszukiwania
bazy \textit{MongoDB}.

\par
W \textit{MongoDB} zaimplementowano interesujący mechanizm uaktualniania danych, który oprócz tradycyjnego podmienia całego dokumentu, umożliwia również
modyfikację wartości pojedynczych atrybutów. Zmiany te są atomowe, to znaczy, że wykonywane są wszystkie zaplanowane zmiany lub żadna, a system wraca do 
stanu początkowego. Jest to pewnego rodzaju namiastka systemu transakcji, znanego z relacyjnych baz danych.

\par
Omawiana baza danych posiada wsparcie dla przetwarzania opartego o wzorzec \textit{Map/Reduce}. Co więcej, mechanizm uruchamiania zadań mapujących 
i agregujących jest bardzo przejrzysty i prosty. Realizowany jest za pomocą jednej metody z biblioteki połączeniowej. Warto nadmienić, że dla
\textit{MongoDB} jest on odpowiednikiem klauzuli \textit{GROUP BY} znanej z języka \textit{SQL}.

\par
Jedną z funkcjonalności, która wyróżnia \textit{MongoDB} na tle innych baz danych \textit{NoSQL}, takich jak \textit{Cassandra} oraz \textit{RavenDB},
jest możliwość przechowywania w niej dużych plików. Odbywa się to przy zastosowaniu specjalnego standardu zapisu, o nazwie \textit{GridFS}, opisanego
w pozycji \cite{mongodb_gridfs}. Dzięki jego wykorzystaniu możliwe jest przechowywanie dużych plików, tak samo, jak przechowywane są dokumenty,
bez spadku wydajności całego systemu bazodanowego.

\par
Kolejnym bardzo ciekawym elementem, wyróżniającym tę bazę danych na tle innych, jest sposób komunikacji. Powłoka tej aplikacji funkcjonuje jako
kompletny interpreter języka \textit{JavaScript}. Dzięki temu zarządzanie oraz manipulacja danymi zawartymi w bazie sprowadza się \textit{de-facto}
do pisania skryptów w tym języku.

\par
\textit{MongoDB} jest jedną z najczęściej stosowanych baz danych typu \textit{NoSQL}. Jest wykorzystywany między innymi w takich firmach, jak 
\cite{mongodb_testimonials}:

\begin{itemize}
	\item \textit{SAP} - Jako baza danych dla systemu \textit{ECM} w ofercie systemu \textit{PaaS}
	\item \textit{MTV} - Jako baza danych dla systemu \textit{CMS}, który w niedalekiej przyszłości będzie zarządzał zawartością
	wszystkich stron podległych tej stacji telewizyjnej.
	\item \textit{SourceForge} - Jako baza danych przechowująca informacje o stronie głównej, stronach projektów oraz stronach pobrań
	każdego z projektów.
\end{itemize}


\subsubsection {Model danych}

\textit{MongoDB}, podobnie jak \textit{RavenDB}, jest bazą danych o modelu danych opartym na dokumentach. Każdy z dokumentów przechowywany jest w jakiejś
kolekcji. Kolekcje są to zbiory dokumentów, które powinny w pewien sposób być ze sobą spójne pod względem zawartości danych. Nie ma jednak żadnego
odgórnego mechanizmu, sprawdzającego spójność właściwości dokumentów w kolekcji. Kolekcja jest odpowiednikiem tabeli w relacyjnej bazie danych.

\par
Co więcej, w przeciwieństwie do kolekcji w systemie \textit{RavenDB}, gdzie stanowią one jedynie logiczną organizację danych, w systemie \textit{MongoDB}
dokumenty w obrębie jednej kolekcji są fizycznie przechowywane w innych plikach na dysku. Z tego względu podejście oparte na tworzeniu jednej kolekcji
dla wszystkich dokumentów nie jest rekomendowane, zarówno z powodów architektonicznych, jak i wydajnościowych.

\par
Każdy dokument jest przechowywany w formacie \textit{BSON}. Jest to format oparty na \textit{JSON}, który został zastosowany w poprzednio omawianej
bazie danych \textit{RavenDB}. Zgodnie z założeniami tego formatu, każdy dokument typu \textit{JSON} zostaje specjalnie zakodowany na postać binarną.
Niewątpliwą zaletą tego formatu jest brak konieczności konwersji dokumentów z postaci tekstowej do binarnej. Dodatkowo posiada on informacje o typach
zapisanych w nim właściwości. Dokumenty zapisane w formacie \textit{JSON} nie posiadają takich informacji.

\par
Wielkość każdego z dokumentów w systemie \textit{MongoDB} jest ograniczona do \textit{16MB} \cite{mongodb_documents}. Warto zauważyć, że nie jest to 
ograniczenie związane z implementacją tej bazy danych. Ma ono na celu uświadomienie architektowi bazy danych, że jeśli jego projekt zakłada istnienie
dokumentów, które przekraczają ten rozmiar, to najprawdopodobniej można go uprościć, a tym samym znacznie przyspieszyć działanie całego systemu.
Należy pamiętać, że jeśli dokument miałby rozmiar około \textit{12,5MB}, to przy standardowym łączu \textit{Ethernet}, pobranie go zajmowałoby całą sekundę,
co oznaczałoby, że baza danych na sekundę stałaby się z punktu widzenia klientów niedostępna.

\par
Jednym z najważniejszych aspektów, na który należy zwrócić uwagę podczas projektowania dokumentowej bazy danych, są relację pomiędzy obiektami.
Istnieją dwa sposoby rozwiązywania problemu relacji. Pierwszym z nich jest załączenie jednego dokumentu w drugim. Podejście to sprawdza się bardzo 
dobrze w przypadku występowania agregatu oraz encji pobocznych. W tym przypadku agregat jest głównym dokumentem, natomiast wszystkie encje towarzyszące
są w nim załączone. Podejście takie ma niewątpliwa zaletę, jest bardzo szybkie oraz proste do zaimplementowania po stronie bazy danych.

\par
Problem powstaje, jeśli dana encja jest współdzielona pomiędzy różne agregaty lub wręcz jeśli nasz model wymaga połączenia pomiędzy agregatami. W takim 
przypadku opisane podejście prowadziłoby do duplikacji danych, a w ostateczności do ich niespójności. W celu rozwiązania tego problemu należy zastosować
podejście znane z relacyjnych baz danych i odwołać się do drugiego dokumentu poprzez wartość klucza innego dokumentu. Warto pamiętać, że w 
\textit{MongoDB} nie występuje operacja \textit{JOIN}. Z tego względu wszystkie operacje połączenia muszą odbyć się po stronie klienta. Jest to 
rozwiązanie mniej wydajne oraz cięższe w implementacji, ponieważ w dokumentowych bazach danych preferowane jest podejście pierwsze.

\par
Co więcej, jeśli zdecydujemy się na rozwiązanie zakładające odwoływanie się do dokumentów poprzez wartość klucza, \textit{MongoDB} w żaden sposób
nie zadba o spójność danych w przypadku, gdy dokument, do którego się odnosimy, zostanie usunięty. Jest to związane z brakiem statycznego schematu
właściwości każdego z dokumentów.

\par
Jak już zostało wspomniane wcześniej, \textit{MongoDB} nie wspiera operacji \textit{JOIN}. Jest to podyktowane wymaganiami wydajnościowymi.
Nietrudno sobie wyobrazić sytuację, gdy w rozproszonej bazie danych wykonywana jest operacja połączenia danych z kilku kolekcji rozdystrybuowanych 
na sto węzłów. Wydajność takiej operacji byłaby nieakceptowalna, nie wspominając o problemach związanych z implementacją takiej funkcjonalności.

\par
\textit{MongoDB} nie wspiera w pełni zasady \textit{ACID}, jednak dostarcza pewnych mechanizmów, które zapewniają niepodzielność oraz spójność 
pewnych operacji na danych w obrębie pojedynczego dokumentu. Przykładem może być zmiana wartości właściwości w obrębie jednego dokumentu, w zależności od
wartości innych właściwości tego samego dokumentu. Z tego względu należy pamiętać, że jeśli projektowana przez nas baza danych posiada pewne
elementy, które wymagają niepodzielności operacji, muszą one odnosić się do tego samego dokumentu. Jeśli zmiany w jednym dokumencie byłyby uwarunkowane danymi znajdującymi się w drugim,
brak jest gwarancji, że operacja taka byłaby atomowa.

\par
W celu przyspieszenia działania wyszukiwania w bazie danych \textit{MongoDB} należy wykorzystać mechanizm indeksów. Jest on analogiczny do 
podejścia znanego z relacyjnych baz danych. Na każdej właściwości w kolekcji dokumentów, po której mamy zamiar wyszukiwać, powinien być założony indeks.
Dzięki temu baza danych może wstępnie posortować takie dokumenty, a co za tym idzie, dostęp do nich oraz wyszukiwanie w ich obrębie jest znacznie 
przyspieszone. Warto zauważyć, że indeksy w bazie danych \textit{MongoDB} są zorganizowane w strukturę \textit{B-drzewa}, czyli tak samo jak w 
większości relacyjnych baz danych.

\par
Jest rzeczą niezwykle istotną, aby już na etapie tworzenia bazy danych założyć odpowiednie indeksy. Zakładanie ich podczas działania systemu wiąże się
ze znaczącym chwilowym spadkiem wydajności systemu, związanym z koniecznością posortowania danych. Co więcej, indeksy w \textit{MongoDB}, w 
przeciwieństwie do mechanizmu indeksowania \textit{RavenDB}, działają inaczej i domyślnie podczas ich tworzenia uniemożliwiają dostęp do danych.
Co prawda istnieje możliwość uruchomienia ich w tle, dzięki czemu przełączenie z kolekcji niezindeksowanej na zindeksowaną następuje dopiero po 
utworzeniu indeksu, jednak nadal wiąże się to z przeznaczeniem dużej ilości mocy obliczeniowej na sortowanie danych.

\par
Podobnie jak w relacyjnych bazach danych, \textit{MongoDB} zapewnia możliwość utworzenia indeksu obejmującego kilka właściwości na raz. Warto zauważyć
również, że indeks taki umożliwia wyszukiwanie oraz sortowanie danych po dowolnym początkowym podzbiorze właściwości wchodzących w skład tego indeksu.

\par
Istnieje jedna zasadnicza różnica pomiędzy indeksami w relacyjnych oraz dokumentowych bazach danych. Większość relacyjnych baz danych
nie umożliwia założenia indeksu na tabeli posiadającej wartości, które mogą przyjąć wartość \textit{NULL}. Ponieważ dokumentowe bazy danych nie 
sprawdzają wewnętrznej spójności struktury dokumentów, może istnieć sytuacja, w której do tabeli posiadającej indeks spróbujemy dodać dokument 
nie posiadający indeksowanej właściwości. Operacja taka powiedzie się jedynie, jeśli indeks został stworzony z opcją \textit{sparse}.
Jest to specjalny rodzaj indeksu, który nie uwzględnia dokumentów nie zawierających indeksowanej właściwości. Warto również zauważyć, że podczas
wykonywania zapytania na takim indeksie, dokumenty w danej kolekcji, nie posiadające indeksowanej właściwości, nie zostaną uwzględnione w
wynikach. Co więcej, indeks typu \textit{sparse} nie może zostać utworzony jako indeks zawierający wiele kolumn.


\par
\textit{MongoDB} podobnie jak \textit{RavenDB} posiada pewien mechanizm zapewniający umieszczanie w bazie danych dużych elementów, przekraczających
limit wielkości dokumentu \textit{16MB}. Nazywa się on \textit{GridFS} i umożliwia przechowywanie w systemie danych binarnych, podobnie jak 
mechanizm załączników umożliwiał to w bazie \textit{RavenDB}. Istota jego działania jest bardzo prosta i opiera się na podziale danego dużego
pliku binarnego na mniejsze części oraz przechowywanie ich tak samo, jakby były one zwykłymi dokumentami. Dzięki temu możliwy jest odczyt danych
partiami, co jest wyjątkowo przydatne w przypadku przechowywania na przykład zbiorów filmowych na potrzeby \textit{streamingu} 
\cite{rfc_streaming}.

\subsubsection {Architektura}

\textit{MongoDB}, podobnie jak dwie poprzednio omawiane bazy danych, składa się z kilku komponentów. Pierwszym oraz najważniejszym z nich jest \textit{mongod}.
Jest to usługa, która odpowiada za działanie bazy danych. Jest ona uruchamiana w trybie \textit{daemon} w systemach \textit{Unix} oraz jako \textit{Windows Service}
w systemie \textit{Windows}. Jest to jedyny komponent niezbędny do działania całego systemu, stanowi on odpowiednik programu \textit{mysqld} w systemie \textit{MySQL}.
Jest on zdolny do samodzielnego wykonania replikacji danych pomiędzy różne węzły sieci.

\par
Kolejnym składnikiem systemu jest \textit{mongos}. Jest to proces odpowiedzialny za partycjonowanie danych w systemie \textit{MongoDB}. W pewnym sensie można porównać ten 
proces do routera, który sprawia, że dla zewnętrznych klientów baza danych wydaje się być tworem spójnym oraz jednorodnym.

\par
Bardzo ważnym komponentem, z punktu widzenia administracyjnego, jest interaktywna konsola \textit{mongo}. Warto wspomnieć, że konsola ta działa jako kompletny interpreter
języka \textit{JavaScript}. Wszystkie komendy bazy danych \textit{MongoDB} są funkcjami pewnych obiektów tego języka. Jest to cecha niespotykana, jeśli weźmiemy 
pod uwagę wcześniej analizowane systemy, jednak bardzo ciekawa oraz niezwykle przydatna. Znacznie upraszcza pisanie bibliotek klienckich, gdyż sprowadzają się one jedynie do przetłumaczenia
serii komend danego języka na wywołania \textit{JavaScript}.

\par
\textit{MongoDB} posiada również wiele narzędzi pozwalających na zarządzenie całym systemem, między innymi:

\begin{itemize}
	\item \textit{mongoimport} - narzędzie pozwalające na import danych do węzła sieci bazy. Dane zawarte powinny być w pliku, w którym na każdą linię przypada jeden obiekt zapisany w formacie
		\textit{JSON/CSV/TSV}. Narzędzie to powinno być wykorzystywane do importu danych z niezależnego źródła lub bazy danych \textit{MongoDB} o innej wersji.
		
	\item \textit{mongoexport} - narzędzie pozwalające na eksport danych z węzła sieci bazy. Działa ono w sposób analogiczny do \textit{mongoimport}.
	
	\item \textit{mongodump} - narzędzie pozwalające na stworzenie kopii bezpieczeństwa danych zawartych w bazie, podczas jej działania. W odróżnieniu od \textit{mongoexport},
		plik wynikowy jest binarną reprezentacją całej bazy danych i z tego powodu jego przenośność pomiędzy wersjami bazy danych \textit{MongoDB} nie jest gwarantowana.
		
	\item \textit{mongorestore} - narzędzie pozwalające na przywrócenie stanu bazy danych na podstawie pliku stworzonego przez narzędzie \textit{mongodump}.
	
	\item \textit{bsondump} - jest to bardzo ciekawe narzędzie, które pozwala na konwersję pliku wykonanego przy pomocy \textit{mongodump} na format \textit{BSON}.
\end{itemize}

\subsubsection {Biblioteki klienckie}

Biblioteki klienckie w nomenklaturze \textit{MongoDB} nazywają się \textit{drivers} i  dzielą się na dwie grupy. Pierwszą z nich stanowią biblioteki posiadające oficjalne wsparcie 
producentów bazy danych. W ich skład wchodzą biblioteki stworzone dla takich języków programowania jak: \textit{C, C++, Erlang, Haskell, Java, JavaScript, C\#, Perl, PHP, Python, Ruby, Scala}
\cite{mongodb_drivers}.

\par
Kolejną grupę tworzą biblioteki stworzone przez społeczność \textit{MongoDB}. Nie posiadają one gwarancji producenta ani nie są oficjalnie wspierane, jednak można wśród nich znaleźć wersję 
dla praktycznie każdego znanego języka programowania.

\par
Ze względu na dużą ilość bibliotek klienckich postanowiono poddać analizie jedną z nich. Jako przykład postanowiono wybrać bibliotekę stworzoną dla platformy \textit{.NET}. Wybór taki został
podyktowany możliwością porównania tej biblioteki z biblioteką dostępową, stworzoną dla \textit{RavenDB}, która również oparta była o technologię \textit{.NET}.

\par
Biblioteka ta składa się z dwóch głównych komponentów. Pierwszym z nich jest \textit{MongoDB.Bson.dll}. Jest on odpowiedzialny za wszystkie operacje, wykorzystujące format \textit{BSON}.
Drugim z nich jest \textit{MongoDB.Driver.dll}. Zawiera on w sobie wszystkie klasy niezbędne do połączenia oraz transmisji danych pomiędzy klientem a bazą danych \textit{MongoDB}.

\par
Dostęp do danych zgromadzonych w bazie danych może być realizowany w dwojaki sposób, wykorzystujący serializację obiektów typu \textit{POCO} do \textit{BSON} lub nie.
Jeśli zdecydujemy się wykorzystać drugi sposób, który na początku może wydawać się znacznie prostszy niż pierwszy, należy zwrócić szczególną uwagę na klasę \textit{BsonDocument}.
Reprezentuje ona pojedynczy dokument \textit{BSON}, który chcemy zapisać do bazy danych. Na listingu \ref{mongodb_create_entity} zaprezentowano przykład stworzenia dokumentu z zagnieżdżonym innym dokumentem.

\begin{lstlisting}[label=mongodb_create_entity,caption=Przykład stworzenia dokumentu z zagnieżdżonym innym dokumentem]
BsonDocument worker = new BsonDocument {
    { "name", "Joe Celco" },
    { "address", new BsonDocument {
        { "street", "24 oak lane" },
        { "city", "leeds" }
    }}
};
\end{lstlisting}

Jak widać, konstrukcja ta bardzo przypomina tworzenie klas implementujących interfejs \textit{IDictionary\textless K, V\textgreater}. Podejście to posiada jednak dwie bardzo duże wady.
Pierwszą z nich jest brak jakiegokolwiek sposobu sprawdzenia, czy przy dodawaniu dokumentów do kolekcji nie popełniliśmy literówki, skutkującej dodaniem dokumentu z niepoprawną właściwością.
W przypadku wykorzystania obiektów typu \textit{POCO}, nie ma takiej możliwości, ze względu na mocną typizację kodu kompilowanego.

\par
Kolejną wadą tego typu rozwiązania jest brak silnego typizowania. Pod właściwość \textit{name} z przykładu możemy podstawić właściwie dowolną wartość. Może to sprawiać dużo problemów
podczas odczytu danych z bazy.

\par
Następną wadą tego rozwiązania jest konieczność stosowania tak zwanych magicznych łańcuchów znaków, opisujących nazwy właściwości, co czyni kod mniej przejrzystym oraz czytelnym.
Rozwiązaniem tego problemu mogłoby być wykorzystanie obiektu \textit{DynamicObject}, który został wprowadzony do \textit{.NET 4.0}. Stworzenie klasy obudowującej \textit{BsonDocument},
opartej na \textit{DynamicObject}, dałoby nie tylko możliwość tworzenia encji bez użycia magicznych łańcuchów, lecz również umożliwiłoby sprawdzenie, w czasie wykonania programu, czy programista nie
popełnił literówki. Co więcej, jeśli cały kod zapisujący dane do bazy zostałby objęty testami jednostkowymi, sprawdzenie poprawności nazw mogłoby odbywać się jako warunek konieczny powodzenia procesu
kompilacji.

\par
Kolejną bardzo istotną klasą, z punktu widzenia komunikacji z bazą danych, jest klasa \textit{MongoServer}. Modeluje ona połączenie z bazą danych \textit{MongoDB}. Za jej pomocą
możemy pobrać kolekcję dokumentów, jak również wykonać niektóre czynności administracyjne.

\par
W celu dodania elementu do kolekcji musimy wykorzystać klasę \textit{MongoCollection\textless T\textgreater}. Jej instancje możemy otrzymać poprzez wykorzystanie metody 
\textit{.GetCollection\textless BsonDocument\textgreater()},
klasy \textit{MongoServer}. Klasa reprezentująca kolekcje posiada komplet metod odpowiedzialnych za zapis, odczyt oraz wyszukiwanie danych w obrębie kolekcji.

\par
\textit{MongoDB} posiada wsparcie dla serializacji obiektów do formatu \textit{BSON}. Jest to alternatywny sposób dostępu do dokumentów, dzięki któremu nie musimy wykorzystywać klasy 
\textit{BsonDocument}, tylko możemy operować na encjach. W celu skorzystania z serializacji musimy utworzyć mapowania właściwości encji na właściwości dokumentów. 
Proces ten bardzo przypomina tworzenie mapowania relacyjno-obiektowego, które znamy z bibliotek \textit{ORM}, takich jak na przykład \textit{NHibernate}. 

\par
Istnieją dwie metody tworzenia mapowań. Pierwszą z nich jest zastosowanie możliwości automatycznego mapowania, opartego na systemie modyfikowalnych konwencji. Podejście to jest bardzo podobne do 
tego zastosowanego w bibliotece \textit{FluentNHibernate}.

\par
Drugą z nich jest stworzenie mapowań za pomocą specjalnych atrybutów, dekorujących właściwości w klasach. Podejście takie również jest umożliwiane przez większość bibliotek typu \textit{ORM},
w szczególności \textit{NHibernate}. Warto zauważyć, że zarówno pierwszą, jak i drugą metodą można utworzyć kompletne mapowanie.


\par
Jak widać, architektura biblioteki klienckiej \textit{MongoDB} różni się znacznie od tej przyjętej na potrzeby \textit{RavenDB}. Po pierwsze, \textit{RavenDB} nie umożliwia dostępu
do dokumentów w postaci słownikowej. Po drugie, jest on oparty na interfejsach, klasach implementujących te interfejsy oraz fabrykach. Podejście takie znacznie upraszcza tworzenie testów jednostkowych 
oraz pozytywnie wpływa na możliwość rozbudowy biblioteki oraz przejrzystość kodu.

\subsubsection {Funkcjonowanie w środowisku rozproszonym}

Podobnie jak poprzednio omawiane bazy danych, \textit{MongoDB} bardzo dobrze działa w środowisku rozproszonym. Posiada wbudowane wsparcie dla mechanizmu partycjonowania oraz replikacji danych.
Co więcej, pozwala w bardzo prosty sposób uruchamiać zadania typu \textit{Map/Reduce}.

\par
Replikacji w bazie danych \textit{MongoDB} można dokonać na dwa sposoby. Pierwszy z nich, znacznie starszy i mniej wydajny, opiera się na replikacji danych pomiędzy jednym arbitralnie wybranym
węzłem typu \textit{master} oraz \textit{slave}. Nie jest on zalecany do wykorzystywania w nowych projektach, gdyż został zastąpiony nowym oraz lepszym mechanizmem, opartym o tak zwane
\textit{Replica Sets}. Jest to forma asynchronicznej replikacji danych pomiędzy co najmniej dwoma
węzłami klastra. Dzięki nim zapewnione jest odtworzenie zawartości bazy danych w przypadku awarii jednego z węzłów oraz automatyczne przełączenie pomiędzy węzłami, tak zwany \textit{failover}.
Warto zauważyć, że wybór jednostki \textit{master} oraz \textit{slave} dokonuje się w sposób automatyczny i domyślnie nie wymaga konfiguracji. Jest to opcja bardzo wygodna oraz znacznie ułatwiająca
administrowanie systemem.

\par
Jak już zostało wspomniane wcześniej, mechanizm partycjonowania danych jest bardzo ważny zarówno z przyczyn wydajnościowych jak i zwiększenia bezpieczeństwa oraz szybkości odpowiedzi systemu.
Uruchomienie mechanizmu partycjonowania składa się z dwóch zasadniczych kroków. Pierwszym z nich jest poprawna konfiguracja mechanizmu \textit{Replica Set}, tak, aby dane były odpowiednio rozdystrybuowane
w obrębie klastra. Warto zauważyć, że dodatkowo należy zmienić priorytety węzłów tak, aby z góry dało się określić, która jednostka będzie typu \textit{master}, a która \textit{slave}.
Po odpowiednim skonfigurowaniu mechanizmu \textit{Replica Set} należy włączyć mechanizm partycjonowania za pomocą funkcji \textit{adminCommand} z parametrem \textit{addShard}.

\par
\textit{MongoDB} posiada bardzo prosty oraz przydatny mechanizm uruchamiania zadań typu \textit{Map/Reduce}. Warto pamiętać, że ze względu na rozdystrybuowanie danych pomiędzy różne węzły
klastra, nie jest możliwe wykonanie operacji znanej z \textit{SQL} o nazwie \textit{GROUP BY}. Zamiast tego uruchamiane są zadania \textit{Map/Reduce}, które zbierają dane z różnych węzłów.

\par
Uruchomienie tego typu zadania w omawianym systemie sprowadza się do odpowiedniego wywołania metody \textit{mapReuce}, obecnej w każdym obiekcie reprezentującym kolekcje. Jako argumenty tej metody 
muszą być podane dwie funkcje. Pierwsza z nich za pomocą wywołań metody \textit{emit} ma za zadanie dokonać projekcji danych. Druga z nich za pomocą zwykłej komendy \textit{return} ma za zadanie dokonać
agregacji danych. Istnieje możliwość podania trzeciej metody, która dokona dodatkowych modyfikacji w zbiorze wyjściowym. Wartością zwracaną przez metodę \textit{mapReduce} jest wynik działania operacji 
agregacji.

\subsubsection {Podsumowanie}

\textit{MongoDB} jest bardzo dobrze zaprojektowanym oraz działającym systemem bazodanowym. Dane w niej zebrane są przechowywane w postaci dokumentów. Jako wewnętrzny format przechowywania danych 
projektanci zdecydowali się wykorzystać format \textit{BSON}, który łączy w sobie zalety przenośności formatu \textit{JSON} z wydajnością formatów binarnych.

\par
Baza ta oferuje bardzo wiele metod dostępowych. Konsola, pozwalająca na manipulację danymi oraz uruchamianie zadań administracyjnych, została stworzona jako interpreter języka \textit{JavaScript}.
Jest to pomysł bardzo oryginalny, jednak ogromnie upraszczający korzystanie z bazy danych oraz tworzenie bibliotek dostępowych. Istnieje bardzo duża ilość bibliotek klienckich dla każdego bardziej 
popularnego języka programowania. Duża część z nich ma oficjalne wsparcie producenta.

\par
Koleją bardzo istotną zaletą bazy danych \textit{MongoDB} jest bardzo obszerna i wyczerpująca dokumentacja. Program ten posiada wsparcie komercyjnej firmy oraz bardzo szerokie grono 
zwolenników oraz deweloperów, którzy wkładają wiele wysiłku w ulepszanie tego produktu. Jest to jeden z powodów, dla których \textit{MongoDB} działa jako baza danych w takich firmach jak:
\textit{Disney}, \textit{MTV} oraz \textit{SourceForge}.

\par
\textit{MongoDB} bardzo dobrze radzi sobie z funkcjonowaniem w środowisku rozproszonym. Posiada wbudowane wsparcie dla mechanizmu replikacji oraz partycjonowania danych.
Umożliwia uruchamianie w prosty sposób zadań typu \textit{Map/Reduce}. Co więcej, dzięki zastosowaniu języka \textit{JavaScript} jako interfejsu komunikacji, 
metody projekcji oraz agregacji danych mogą być w nim stworzone.

\subsection{Podsumowanie}

Bazy danych typu \textit{NoSQL} stanowią bardzo szerokie pole badań. Różnią się od siebie pod bardzo wieloma względami, jednak aspektem, który je wszystkie łączy, jest odrzucenie
zastosowania modelu relacyjnego przy projektowaniu modelu danych. Zamiast tego implementują one model dokumentowy, obiektowy lub zorganizowane są w postaci wielkich zbiorów typu \textit{klucz - wartość}.

\par
W pracy tej dokładnie przeanalizowano trzy bazy danych typu \textit{NoSQL}: \textit{RavenDB}, \textit{MongoDB} oraz \textit{Cassandra}. Każda z nich różniła się od pozostałych w bardzo istotnych 
aspektach, jak między innymi, model danych, podejście do funkcjonowania w środowisku rozproszonym oraz ilość i różnorodność bibliotek klienckich. Podstawowe porównanie zbiorcze zostało przedstawione
w tabeli \ref{analiza_zbiorcza}.

\par
Po dokonaniu analizy oraz zaimplementowaniu testów z rozdziału "Analiza wydajnościowa", okazało się, że model dokumentowy jest znacznie bliższy modelowi obiektowemu. Zapis obiektowych encji
do dokumentowej bazy danych odbywał się praktycznie automatycznie. Dzięki temu zachowana była dużo większa przejrzystość kodu oraz łatwość implementacji. 
Wykorzystanie bazy danych \textit{Cassandra} było odrobinę bardziej problematyczne, gdyż wymagało zastosowania mapowania pomiędzy właściwościami encji a kolumnami w tabeli. 

\par
Najbardziej rozbudowane wsparcie dla platformy \textit{.NET} posiadały bazy danych \textit{RavenDB} oraz \textit{MongoDB}. Ta ostatnia posiadała również znacznie bogatszy zasób metod optymalizujących
korzystanie z bazy danych. Obydwie posiadały zaimplementowane własne mechanizmy tłumaczenia zapytań \textit{LINQ} na wewnętrzny mechanizm wyszukiwania danych. Dzięki temu pozyskiwanie danych z bazy
mogło być realizowane w bardzo prosty sposób.

\par
Wszystkie trzy bazy danych posiadały wsparcie dla indeksowania danych. Warto zauważyć, że możliwość indeksowania danych jest kluczowa z punktu widzenia szybkości wyszukiwania danych w bazie.
Nie we wszystkich bazach danych mechanizm ten działał jednak w ten sam sposób. Baza danych \textit{RavenDB} posiada mechanizm indeksowania w tle. Dzięki temu, za cenę nie zawsze spójnego indeksu,
otrzymuje się przyspieszenie zapisywania danych.

\par
Wszystkie analizowane bazy danych posiadały bardzo szerokie wsparcie dla funkcjonowania w środowisku rozproszonym, jednak najlepiej problem ten został rozwiązany w systemie \textit{Cassandra}.
Jest ona oparta na modelu zaproponowanym przez \textit{Amazon Dynamio} i cechuje się brakiem wąskich gardeł i wieloma ciekawymi strategiami replikacji oraz partycjonowania danych.
Posiada również bardzo szerokie możliwości rozbudowy tych strategii oraz zastosowanie własnych, działających w zupełnie inny sposób.

\begin{table}
\begin{tabular}{ | p{4cm} |  p{4cm}  |  p{4cm}  |  p{4cm}  | }
\hline & \textit{RavenDB} & \textit{MongoDB} & \textit{Cassandra} \\
\hline Model danych & dokumentowa & dokumentowa & klucz - wartość \\
\hline Wyszukiwanie danych & \textit{LINQ} & szereg metod filtrujących & bardzo rozbudowany język, podobny do \textit{SQL} - \textit{CQL} \\
\hline Indeksowanie danych & na bazie zapytań \textit{LINQ} przeliczanych asynchronicznie w tle & indeksy przeliczane synchronicznie & indeksy przeliczane synchronicznie \\
\hline Wsparcie dla transakcji & całkowite & częściowe & brak \\
\hline Partycjonowanie danych & po zainstalowaniu wtyczki & wbudowane & wbudowane - możliwość stworzenia własnych strategii partycjonowania \\
\hline Replikacja danych & po zainstalowaniu wtyczki & wbudowane & wbudowane - możliwość stworzenia własnych strategii replikacji \\
\hline Wsparcie dla zadań typu \textit{Map/Reduce} & wbudowane & poprzez wykonywanie kodu \textit{JavaScript} na zdalnych węzłach & wbudowane - dodatkowa możliwość podłączenia do klastra \textit{Hadoop} \\
\hline Język implementacji & \textit{C\#} & \textit{C++} & \textit{Java} \\
\hline Oficjalne \textit{API} dla \textit{.NET} & tak & tak & nie \\
\hline Typ licencji & \textit{Open Source} (płatne do zastosowań komercyjnych) & \textit{Open Source} (bezpłatne dla zastosowań komercyjnych) & \textit{Open Source} (bezpłatne dla zastosowań komercyjnych) \\
\hline

\end{tabular}
\caption{Analiza zbiorcza wybranych baz \textit{NoSQL}}
\label{analiza_zbiorcza}
\end{table}

\FloatBarrier

\newpage
\section {Projekt systemu bazodanowego InDB}

Rozdział ten ma na celu opisanie autorskiego systemu bazodanowego o nazwie \textit{InDB}, który został stworzony jako przykład podejścia \textit{NoSQL} w zastosowaniach przemysłowych.

\par
Podejście do przechowywania oraz zarządzania danymi, prezentowane przez większość baz danych typu \textit{NoSQL}, niesie za sobą bardzo wiele pozytywnych konsekwencji. Jedną z nich jest bardziej
obiektowe spojrzenie na przechowywanie danych, znane z dokumentowych baz danych. Dzięki niemu znacznie zmniejsza się między innymi czas tworzenia aplikacji oraz wzrasta poziom ich poprawności
poprzez wyeliminowanie konieczności stosowania bibliotek typu \textit{ORM}.

\par
Praktycznie wszystkie bazy danych typu \textit{NoSQL} zostały stworzone z myślą o systemach webowych oraz aplikacjach wymagających dystrybucji danych na wiele węzłów. Większość z nich posiada
bardzo dobrze zaprojektowane mechanizmy, umożliwiające im działanie w warunkach systemu rozproszonego. Brak im jednak w większości algorytmów zapewniających deterministyczny dostęp do spójnych danych.
\textit{RavenDB} pomimo zastosowania mechanizmu transakcji, dopuszcza istnienie niepełnych indeksów. \textit{MongoDB} pomimo synchronicznego mechanizmu tworzenia indeksów nie dostarcza mechanizmów
umożliwiających tworzenie transakcji.

\par
Ze względu na wyżej wymienione rozwiązania architektoniczne, żadna z analizowanych baz danych nie nadaje się w pełni do zastosowania w warunkach przemysłowych, takich jak akwizycja danych pomiarowych lub
przechowywanie historycznych danych procesu. Najważniejszym aspektem dla tego typu zadań jest bezpieczeństwo, rozumiane poprzez trwałość danych, w połączeniu z szybkim dostępem do nich.

\par
Z tego względu zdecydowano się stworzyć bazę danych typu \textit{NoSQL}, która byłaby zorientowana na działanie w środowisku przemysłowym. Nastawiona byłaby ona przede wszystkim na bezpieczeństwo 
przechowywanych danych, w połączeniu z szybkością w dostępie do nich. Dodatkową zaletą tworzonego systemu byłoby zachowanie prostego mechanizmu dostępu do danych, dzięki któremu niepotrzebne byłoby tworzenie
skomplikowanych systemów mapowania właściwości obiektów z dziedziny aplikacji na odpowiednie pola lub komórki bazy danych.

\par
Rozdział ten został zorganizowany w podrozdziały, które opisują kompletny proces rozwoju bazy danych \textit{InDB}. Zostały one zaczerpnięte z kaskadowego modelu życia oprogramowania, dogłębnie opisanego
w książce \cite{io_wstep} i bardzo dobrze oddają proces tworzenia programu komputerowego.

\subsection {Specyfikacja wymagań}

Jedną z ważniejszych faz rozwoju oprogramowania jest specyfikacja wymagań. Jest to część inżynierii oprogramowania, która dostarcza nam środków oraz metod umożliwiających zebranie informacji na 
temat przyszłej funkcjonalności tworzonej przez nas aplikacji lub systemu komputerowego. 

\par
Warto zauważyć, że popełnienie błędu w tej fazie projektu jest najbardziej kosztowne. Szacuje się, że w modelu kaskadowym błąd popełniony we wcześniejszym kroku propaguje się na kolejne 
w sposób wykładniczy o podstawie dziesięć. Ze względu na to, że jest to pierwsza faza projektu, błędy w niej popełnione propagują się najbardziej.

\par
Dodatkowo, jeśli stworzymy złą specyfikację wymagań, możemy przez cały czas przeznaczony na projekt tworzyć aplikacje, która nie odpowiada potrzebom klienta oraz środowiska. Z tego względu,
pomimo przeznaczenia znacznych środków, klient nie otrzyma produktu, którego potrzebował.

\par
Jednym z lepszych sposobów usystematyzowania wymagań jest zebranie ich oraz zaprezentowanie w postaci tabelki. Tabela \ref{specyfikacja_wymagan} jest realizacją tej koncepcji.
Podzielona jest ona na trzy kolumny. W pierwszej z nich zamieszczona została skrótowa nazwa stawianego przed projektowaną baza wymagania. Druga zawiera bardziej szczegółowy opis wraz z uzasadnieniem.
Ostatnia ocenia jak bardzo istotna jest dana funkcjonalność dla poprawnego działania tworzonej bazy.

\begin{longtable}{ | p{4cm} | p{9cm} | p{3cm} | }
\hline Nazwa skrótowa & Opis oraz uzasadnienie & Poziom istotności \\

\hline Implementacja \textit{CRUD} & Implementacja tych operacji jest jedną z najważniejszych funkcjonalności jakie baza danych powinna posiadać. Dzięki nim możliwe jest dodawanie, odczytywanie oraz 
modyfikacja danych zawartych w bazie. Bez tej funkcjonalności niemożliwe byłoby zarządzanie danymi zgromadzonymi w bazie. Bardzo istotnym jest również, aby operacje te, dla zachowania spójności 
bazy, były atomowe. & Niezbędne \\

\hline Architektura oparta o model klient - serwer & Aplikacja musi być podzielona na część klienta, czyli biblioteki, którą można wykorzystać w jakiejś innej aplikacji oraz serwera, działającego jako usługa,
w sposób nieprzerwany oraz niezależny. Dzięki takiemu podziałowi oraz opracowaniu protokołu komunikacji pomiędzy stronami możemy uzyskać dwa oddzielne podsystemy, które mogą być rozwijane
niezależnie. & Niezbędne \\

\hline Brak potrzeby mapowania obiektowo-relacyjnego & Dzięki zastosowaniu modelu danych, nie wymagającego stosowania rozbudowanego mapowania obiektowo - relacyjnego, możliwym będzie
znaczne skrócenie czasu implementacji aplikacji korzystających z systemu \textit{InDB}. & Bardzo ważne \\

\hline Szybki dostęp do danych, wydajność zapisu oraz odczytu & Wydajność jest bardzo ważnym aspektem każdej bazy danych. Tworzony system również powinien być wydajny, jednak nie jest to jego
najważniejsza cecha. Wydajność powinna być na poziomie innych rozwiązań tego typu dostępnych na rynku. & Bardzo ważne \\

\hline Rozproszenie danych na wiele węzłów w sieci & Wydajność, oprócz efektywnej implementacji, można zwiększyć poprzez rozproszenie aplikacji na różne maszyny. Dzięki tej funkcjonalności
możliwym będzie instalacja bazy danych na wielu węzłach sieci. Warto zauważyć, że oprócz wzrostu wydajności systemu, zyskujemy również zwiększenie bezpieczeństwa przechowywanych danych, poprzez
fakt kopiowania informacji na wiele niezależnych komputerów. & Bardzo ważne \\

\hline Wydajność dla dużej ilości krótkich zapytań & Bardzo często systemy automatyki generują wiele niezależnych od siebie sygnałów. Mogą to być różnego rodzaju alarmy lub odczyty. Charakterystyką
tych informacji jest to, że są one bardzo małe pod względem ilości pamięci potrzebnej na ich utrwalenie oraz pojawiają się bardzo często. Z tego względu projektowana baza danych musi być nastawiona
na efektywne przetwarzanie krótkich zapytań. & Ważne \\

\hline Transakcje & Ważnym aspektem każdej bazy danych jest spójność oraz integralność danych. Jest to bardzo istotne zwłaszcza w zastosowaniach przemysłowych. Jednak transakcje, jakie znamy z 
relacyjnych baz danych, dotyczą głównie zapisu większych porcji danych oraz uaktualniania danych powiązanych. Dzięki temu, że operacje \textit{CRUD} w systemie \textit{InDB} muszą być atomowe oraz
nastawiona ona będzie na przetwarzanie małych porcji danych, implementacja kompletnego systemu transakcyjnego nie jest elementem najbardziej istotnym. & Ważne \\

\hline Łatwość instalacji & Ważnym jest aby system \textit{InDB} był prosty w instalacji. Wiele z analizowanych systemów typu \textit{NoSQL}, pomimo bardzo dużych możliwości, jest bardzo trudna w instalacji.
Z tego względu często są one zainstalowane oraz skonfigurowane nieoptymalnie. Dzięki prostemu systemowi instalacji \textit{InDB} będzie pozbawiony tego mankamentu. & Ważne \\
\hline

\caption{Wymagania stawiane systemowi \textit{InDB}}
\label{specyfikacja_wymagan}
\end{longtable}

\FloatBarrier

\par
Na bazie wymagań zgromadzonych w tabeli \ref{specyfikacja_wymagan} stworzono projekt systemu \textit{InDB}. Został on dokładnie opisany w kolejnym rozdziale.

\subsection {Projekt}

Rozdział ten szczegółowo opisuje projekt systemu \textit{InDB}. Zawiera on wszystkie niezbędne schematy oraz diagramy klas, które stanowią punkt wyjścia dla implementacji tworzonego systemu.
Punktem wyjścia dla projektu były wymagania zgromadzone w tabeli \ref{specyfikacja_wymagan}.

\subsubsection{Model danych}

\par
Najważniejszym aspektem, który musi zostać zaprojektowany na wstępie, jest model danych. Zależy od niego projekt biblioteki klienckiej oraz serwera. Wybranie nieoptymalnego modelu może skutkować
skomplikowaniem projektu oraz zmniejszeniem wydajności ostatecznego wyniku implementacji bazy danych \textit{InDB}.

\par
Po przeanalizowaniu modeli danych opisywanych wcześniej systemów, zdecydowano się, że w projektowanej bazie danych zastosowany zostanie model dokumentowy. 
Jest on najbardziej zbliżony do modelu obiektowego, dzięki czemu spełnione zostanie założenie o braku konieczności dokonywania skomplikowanego mapowania obiektowo - relacyjnego, 
podczas pisania aplikacji wykorzystujących tworzony system.

\par
Jak pokazują przeprowadzone w kolejnym rozdziale badania, baza danych \textit{MongoDB} jest najszybsza w zapisywaniu dokumentów oraz ich kasowaniu. Pokazuje to, że dokumentowy model danych
może zostać zaimplementowany w bardzo wydajny sposób.

\par
Podobnie jak \textit{RavenDB} oraz \textit{MongoDB}, projektowana baza danych nie będzie posiadała statycznego schematu. W celu usystematyzowania danych każdy dokument będzie przynależał do pewnej kolekcji
dokumentów. Nazwa tej kolekcji będzie równoważna z typem dokumentu, jednak ze względu na brak schematu dokumenty w obrębie jednej kolekcji mogą mieć zupełnie inną strukturę oraz pola. 

\par
Co więcej, każdy dokument będzie składał się z dwóch części. Pierwszą z nich stanowią dane zapisane przez użytkownika. Są one całkowicie dowolne i nie podlegają analizie dokonywanej przez serwer. 
Drugą z nich stanowi specjalny zbiór metadanych, które baza powinna przechowywać na temat każdego dokumentu. Do tego zbioru zaliczyć można informacje na temat stworzenia dokumentu, ostatniej 
modyfikacji oraz, co najważniejsze, specjalnego identyfikatora dokumentu. 

\par
Należy pamiętać, że każdy dokument powinien być identyfikowalny na podstawie unikalnego numeru. Ma to bardzo duże znaczenie zwłaszcza podczas projektowania protokołu oraz biblioteki klienckiej. 
Co więcej, dzięki wprowadzeniu liczbowego identyfikatora dostęp do indywidualnych dokumentów można znacznie przyspieszyć.

\par
Model dokumentowy ma wiele zalet. Pierwszą z nich jest jego przejrzystość. W związku z tym, że większość dokumentów w analizowanych bazach danych jest identyczna z modelami encji aplikacji,
przeglądanie danych zgromadzonych w bazie jest bardzo proste. Co więcej, jest on zoptymalizowany pod kątem agregacji dokumentów. W relacyjnej bazie danych, aby otrzymać połączenie wielu tabel należy dokonać
operacji \textit{JOIN}. W dokumentowej bazie danych struktura dokumentów może być drzewiasta. Z tego względu, zamiast wykonywać operacje złączenia, wystarczy pobrać dokument będący korzeniem szukanego
drzewa.


\subsubsection{Protokół komunikacyjny}


\begin{figure}
\centering
\includegraphics{architecture_overview}
\caption{Schemat architektury projektowanego systemu}
\label{architecture_overview}
\end{figure}


\par
Jednym z najważniejszych założeń tworzonego systemu był wyraźny podział na część kliencką oraz serwerową. Dzięki niemu projekt oraz implementacja obydwu podsystemów mogłyby odbywać się niezależnie.
Rysunek \ref{architecture_overview} obrazuje ogólną architekturę projektowanego systemu. Strzałki na rysunku mają swój początek zawsze w jednostce inicjującej komunikację, natomiast grot w komponencie 
docelowym i obrazują, który komponent jest typu \textit{master}, a który \textit{slave}. 

\par
Jak widać system dzieli się on na część kliencką, odpowiedzialną za połączenie z serwerem oraz przetwarzanie danych
po stronie aplikacji klienckiej oraz część serwerową, odpowiedzialną za koordynację operacji, replikacje danych oraz zarządzanie transakcjami.


\par
Warto zauważyć, że jedynym wspólnym aspektem obydwu podsystemów jest protokół komunikacyjny. Umożliwia on wykonanie wszystkich opisanych w założeniach operacji, przy zachowaniu najprostszej specyfikacji.
Ze względu na przeznaczenie powinien on być zaimplementowany na bazie mechanizmu zdalnego wywoływania procedur \cite{rfc_rpc}, przy czym technologia realizująca tego typu operacja powinna być 
niezależna od wybranej technologii implementacji. Dzięki temu klient oraz serwer mogą być, w razie potrzeby, napisane w zupełnie innych językach. Ma to szczególne znaczenie, jeśli chcemy, aby istniała
możliwość napisania oprogramowania klienckiego dla więcej niż jednej platformy.

\par
Projektowany protokół powinien umożliwiać wykonanie następujących operacji.
\begin{itemize}
\item \textit{Get} - Operacja ta na podstawie typu kolekcji, umożliwiałaby pobranie wszystkich dokumentów wraz z ich identyfikatorami.
\item \textit{GetById} - Operacja ta na podstawie dostarczonego identyfikatora dokumentu, zwracałaby jego zawartość.
\item \textit{Save} - Operacja ta na podstawie identyfikatora dokumentu, jego typu oraz zawartości, umożliwiałaby jego zapis lub modyfikację.
\item \textit{Remove} - Operacja ta na postawie identyfikatora dokumentu oraz jego typu, kasowałaby jego zawartość z bazy danych.
\item \textit{DropCollection} - Operacja ta na podstawie typu kolekcji kasowałaby jej całą zawartość.
\item \textit{BeginTransaction} - Operacja ta rozpoczynałaby transakcję dla aktualnego połączenia.
\item \textit{RollbackTransaction} - Operacja ta cofałaby wszystkie zmiany dla aktywnej transakcji połączenia.
\item \textit{CommitTransaction} - Operacja ta zatwierdzałaby wszystkie zmiany dla aktywnej transakcji połączenia.
\end{itemize}

\subsubsection{Biblioteka kliencka}

Po ustaleniu modelu danych oraz protokołu komunikacyjnego, kolejnym krokiem jest zaprojektowanie biblioteki klienckiej. W celu ułatwienia korzystania z projektowanej biblioteki powinna ona wzorować
się na już istniejącym, sprawdzonym rozwiązaniu. Dzięki temu będzie ona bardziej przejrzysta oraz zrozumiała dla nowych programistów korzystających z systemu \textit{InDB}.

\par
Zdecydowano, że będzie ona wzorować się na bibliotece \textit{NHibernate}, podobnie jak w systemie \textit{RavenDB}.
Dzięki dużej popularności tej biblioteki oraz doświadczeniu jej deweloperów jest ona bardzo dobrze zaprojektowana oraz wykonana.
Dodatkowo, dzięki wykorzystaniu interfejsów, programy stworzone przy jej pomocy są znacznie prostsze w testowaniu. Ma to szczególne znaczenie przy projektowaniu aplikacji zgodnie z metodologią 
\textit{TDD}.

\begin{figure}
\centering
\includegraphics{interfaces}
\caption{Główne interfejsy biblioteki klienckiej}
\label{client_interfaces}
\end{figure}

\par
Rysunek \ref{client_interfaces} obrazuje główne interfejsy, które powinny zostać stworzone w bibliotece klienckiej. Głównym obiektem zapewniającym połączenie z bazą danych jest obiekt \textit{ISession}.
Umożliwia on wywołanie każdej metody z protokołu komunikacyjnego. W szczególności odpowiada za rozpoczynanie transakcji, pobieranie danych oraz ich modyfikację.

\par
Interfejs \textit{ITransaction} dostarcza obiektowego opakowania wywołań metod \textit{BeginTransaction}, \textit{RollbackTransaction} oraz \textit{CommitTransaction}. Wykorzystuje on bardzo popularny
w języku \textit{C\#} interfejs o nazwie \textit{IDisposable}. Dzięki niemu oraz wykorzystaniu konstrukcji \textit{using(...)}, można zaimplementować transakcje, która w sposób automatyczny
wywoła operację \textit{rollback} w przypadku wystąpienia jakiegokolwiek wyjątku.

\par
Podobnie jak w bibliotece \textit{NHibernate}, obiekty implementujące interfejs \textit{ISession} są tworzone poprzez specjalną fabrykę \textit{ISessionFactory}. Posiada ona jedną metodę 
\textit{OpenSession},
dostarczającą nową sesję z bazą danych. Dzięki takiemu podejściu, podczas tworzenia testów jesteśmy w stanie zastąpić domyślną fabrykę swoją własną, dostarczającą testowe obiekty, implementujące interfejs
\textit{ISession}.

\par
Podobnie jak w bibliotece \textit{NHibernate}, stworzenie obiektu implementującego \textit{ISession} powinno być czynnością szybką. Obiekty tego typu będą bardzo często tworzone w związku z tym 
zbyt duży narzut czasowy związany z tą operacją byłby nieakceptowalny. W przeciwieństwie do obiektu \textit{ISession} obiekt typu \textit{ISessionFactory} powinien istnieć tylko jeden. Jego stworzenie
może być czasochłonne oraz powinien być on odporny na dostęp z wielu wątków jednocześnie. Obiekty typu \textit{ISession} nie muszą być odporne na wielodostęp.

\par
Kolejnym opisywanym obiektem jest \textit{SessionFactoryFactory}. Jest to obiekt odpowiedzialny za dostarczanie domyślnej implementacji interfejsu \textit{ISessionFactory}. Nie ma on swojego odwzorowania
w bibliotece \textit{NHibenrate}, gdzie obiekt fabryki sesji tworzony jest na podstawie obiektu definiującego konfigurację. Ze względu na prostotę biblioteki klienckiej, jej konfiguracja jest minimalna,
przez co obiekt, definiujący konfigurację i budujący fabrykę sesji, nie jest potrzebny.

\par
Ze względu na częstość tworzenia obiektów typu \textit{ISession} istnieje konieczność trzymania pewnej puli gotowych połączeń z bazą danych. Implementacja musi dostarczyć pewnego obiektu o nazwie
\textit{ConnectionPool}, który umożliwiałby pobranie otwartego, niewspółdzielonego połączenia z bazą danych. Powinien on zostać zaimplementowany zgodnie ze wzorcem \textit{Singleton}.
Dodatkowo, jeśli ilość połączeń w puli zostałaby wyczerpana, powinien on otwierać nowe połączenia. Dzięki takiej implementacji, koszt połączenia z bazą danych mógłby zostać w dużej mierze wyeliminowany.


\subsubsection{Serwer bazy danych}

Kolejnym komponentem systemu \textit{InDB} jest właściwa część serwera bazy danych. Powinien on zostać wykonany w technologii, która umożliwiałaby jego działanie w oderwaniu od sesji użytkownika
danego systemu operacyjnego. Dzięki temu, mógłby działać nieprzerwanie w postaci usługi na serwerowym systemie operacyjnym.

\par
Aplikacja serwerowa ponadto powinna być podzielona na dwie zasadnicze części. Pierwsza z nich obejmowałaby wszystkie klasy odpowiedzialne za logikę działania serwera, jak na przykład przetwarzanie i
uaktualnianie metadanych oraz serwisy obsługujące komunikację sieciową. Druga natomiast powinna zawierać wszystkie algorytmy oraz technologie, zapewniające zapis przetworzonych danych na dysk.

\begin{figure}
\centering
\includegraphics{serverInterfaces}
\caption{Główne interfejsy oraz typy aplikacji serwerowej}
\label{server_interfaces}
\end{figure}

\par
Rysunek \ref{server_interfaces} pokazuje główne interfejsy oraz typy, dostępne w projektowanej aplikacji serwerowej. Pierwszym i jednym z najważniejszych jest klasa \textit{Document}. Modeluje ona
pojedynczy dokument przechowujący dane w bazie. Zgodnie z przyjętym wcześniej założeniem, projektowana baza danych powinna opierać się na modelu dokumentowym. Z tego względu istnieje potrzeba
stworzenia obiektu, który przechowywałby wszystkie informacje oraz metadane każdego dokumentu. Jest ona podstawową oraz niepodzielną jednostką informacji zapisywanej w bazie \textit{InDB}.

\par
Kolejnym interfejsem jest \textit{IDatabaseWebService}. Definiuje on operacje dostępne poprzez technologie zdalnego wywoływania procedur, które mogą być wykorzystane przez użytkownika. Jak widać są one
niemalże identyczne z tymi definiowanymi przez protokół komunikacyjny.

\par
Interfejs \textit{IStorage} należy do części odpowiedzialnej za zapis oraz odczyt danych z dysku. Zapewnia on dostęp do niskopoziomowych metod, operujących na klasie \textit{Document}, dzięki którym
zawartość dokumentów wraz z dotyczącymi ich metadanymi może być w efektywny sposób zapisywana na trwały nośnik danych.

\par
Warto zauważyć, że dzięki odseparowaniu logiki pracy serwera od modułu zapisu, uzyskujemy możliwość zmiany technologii zapisu na dysk. Dzięki temu w prosty sposób możemy stworzyć silnik zapisu danych,
który operowałby jedynie na pamięci operacyjnej. Pomimo tego, że zastosowanie takiego silnika byłoby niedopuszczalne w warunkach produkcyjnych, byłoby idealne w testach akceptancyjnych, gdyż za każdym razem,
gdy serwer byłby resetowany wracałby do pierwotnej konfiguracji. Co więcej, w skrajnym przypadku, algorytmy zapisu danych na dysk mogłyby być oparte o jakąś relacyjną bazę danych. Dzięki temu 
system \textit{InDB} funkcjonowałby jako system zapisujący dokumentowe dane w relacyjnej bazie. Stanowiłoby to połączenie wydajności relacyjnej bazy danych z prostotą funkcjonowania modelu dokumentowego.

\par
Każde środowisko działania systemu \textit{InDB} może się różnić od pozostałych w sposób bardzo drastyczny. Z tego powodu istnieje konieczność konfiguracji każdej instalacji. 
Interfejs \textit{IConfiguration} dostarcza niezbędnych metod, dzięki którym aplikacja może odczytywać indywidualną konfigurację aplikacji. W skład parametrów podlegających konfiguracji wchodzą między 
innymi: ścieżka, gdzie zapisywane powinny być dane, nazwa pliku bazy danych oraz szczegóły dotyczące pracy w środowisku rozproszonym.

\par
Jednym z takich ustawień jest informacja dotycząca tego, czy dany węzeł jest główny czy podrzędny. W celu dokładnego zrozumienia znaczenia tej informacji należy poznać w jaki sposób system \textit{InDB}
powinien funkcjonować w środowisku rozproszonym.

\par
Istnieją dwie główne struktury organizacyjne w sieciach komputerowych: \textit{peer-to-peer} \cite{peertopeer} oraz \textit{master - slave} \cite{master_slave}. Pierwsza z nich zakłada, że wszystkie 
węzły w sieci są równe, jeśli jest wymagana koordynacja niektórych czynności, dobór ról następuje dynamicznie w sposób losowy.

\par
Druga zakłada, że jeden węzeł (\textit{master}) zostaje wyszczególniony i koordynuje pracę węzłów podrzędnych (\textit{slave}). Ze względu na łatwość implementacji oraz powszechne wykorzystanie w systemach 
automatyki, architektura sieciowa systemu \textit{InDB} powinna być oparta o model \textit{master - slave}.

\par
Metoda \textit{IsMasterNode} dostarcza informacji na temat roli węzła w sieci. Domyślnie zwracana wartość jest \textit{false}. Co więcej, należy 
bezwzględnie zadbać o to, żeby tylko jeden węzeł w sieci pełnił rolę \textit{master}. W przeciwnym razie może dojść do konfliktów oraz niespójności danych.

\par
Mechanizm replikacji w systemie \textit{InDB} powinien działać w sposób następujący. Odczyt danych powinien być możliwy z każdego węzła, natomiast zapis danych powinien być możliwy jedynie przy wykorzystaniu
węzła \textit{master}, który, wykonując odpowiednie metody protokołu komunikacji, dokonywałby synchronizacji danych we wszystkich węzłach \textit{slave}. Synchronizacja taka powinna mieć charakter 
synchroniczny oraz powinna spełniać założenia opisane w pozycji \cite{acid}.

\par
W bardzo podobny sposób powinien działać mechanizm transakcji. Rozpoczęcie transakcji powinno być możliwe jedynie przy użyciu węzła \textit{master}. 
Po wykonaniu tej operacji rozpoczynałby on również transakcje
w węzłach typu \textit{slave}. Po dokonaniu zmian w danych oraz zsynchronizowaniu ich z innymi węzłami, transakcje byłyby po kolej zatwierdzane lub cofane. Dzięki temu dane w każdym węźle byłyby spójne.

\par
Pomimo wielu zalet, architektura \textit{master - slave} posiada jeden istotny mankament. Zakłada ona, że węzeł master musi być cały czas dostępny, gdyż w przypadku jego awarii brak jest koordynatora
operacji modyfikacji danych. Problem ten da się jednak w prosty sposób rozwiązać poprzez zastosowanie odpowiedniej konfiguracji. Dzięki zastosowaniu maszyn wirtualnych oraz mechanizmu \textit{failover}
pomiędzy nimi, możemy w rzeczywistości posiadać kilka takich samych instancji węzła master, czekających w uśpieniu. Jeśli system wykryje awarię aktualnie używanego, natychmiastowo któryś z 
zapasowych przejmuje jego rolę.

\par
Projekt opisany w tym rozdziale powinien stanowić punkt wyjścia dla implementacji opisanej w rozdziale kolejnym.


\subsection {Implementacja}

Rozdział ten opisuje w sposób szczegółowy etap implementacji systemu \textit{InDB}. Zawiera on opis wszystkich technologii oraz koncepcji towarzyszących etapowi implementacji. Stanowi on również
pełną instrukcję, dotyczącą instalacji oraz konfiguracji systemu.

\par
Projekt zdecydowano się zaimplementować w oparciu o technologie \textit{.NET 4.0} oraz język programowania \textit{C\#}. Jako środowisko deweloperskie zdecydowano się wykorzystać \textit{Microsoft Visual
Studio 2010 - Ultimate}. Dodatkowo, w celu uproszczenia procesu zarządzania kodem, zdecydowano się wykorzystać system kontroli wersji \textit{SVN}. Jako serwer \textit{SVN} zdecydowano się 
wybrać serwis \textit{Google Code}. Jego niewątpliwymi zaletami jest stabilność oraz darmowy dostęp.

\par
Zgodnie z założeniami projektu implementację systemu \textit{InDB} podzielono na dwa etapy. Pierwszym z nich była implementacja serwerowej części. Po jej zakończeniu rozpoczęto etap implementacji
części klienckiej. Rozdział ten został podzielony na podrozdziały kolejno opisujące szczegóły implementacji komponentów opisanych w projekcie.

\par
Bardzo ważną rzeczą podczas implementacji jest podział solucji na odpowiednie projekty. Powinny one pokrywać się z komponentami wyszczególnionymi w procesie projektowania. Dzięki temu możemy w efektywny
sposób wykorzystać hermetyzację na poziomie projektu oraz uzyskać niezależność pomiędzy komponentami. Poniżej zamieszczono listę bibliotek, na które projekt został podzielony.

\begin{itemize}
\item \textit{InDB.Client} - Biblioteka ta odpowiada za całą funkcjonalność kliencką.
\item \textit{InDB.Core} - Biblioteka ta odpowiada za wszystkie wspólne aspekty części zarówno serwerowej, jak i klienckiej.
\item \textit{InDB.Database.Core} - Biblioteka ta odpowiada za część wspólną różnych komponentów, wchodzących w skład aplikacji serwerowej.
\item \textit{InDB.Database.Domain} - Biblioteka ta zawiera w sobie wszystkie interfejsy, definiujące komponenty serwerowej części implementowanego systemu.
\item \textit{InDB.Database.Service} - Biblioteka ta zawiera w sobie klasy odpowiadające za uruchamianie programu w trybie usługi \textit{Windows} oraz komunikację za pomocą protokołu z klientami.
\item \textit{InDB.Database.Storage} - Biblioteka ta zawiera klasy implementujące funkcjonalność zapisu danych na nośnik danych.
\end{itemize}

\subsubsection{Część wspólna oraz protokół}

Przed rozpoczęciem implementacji biblioteki klienckiej oraz aplikacji serwerowej, bardzo istotnym krokiem było wybranie technologii realizującej zdalne wywoływanie procedur. Ze względu na wykorzystanie
\textit{.NET Framework} zdecydowano się zastosować bibliotekę \textit{WCF} \cite{wcf_overview}. 

\par
Jest to bardzo rozbudowana biblioteka umożliwiająca zdalne wywoływanie procedur przy wykorzystaniu wielu protokołów, między innymi \textit{HTTP} w postaci wywołań \textit{SOA Web Service},
\textit{HTTPS} oraz \textit{TCP} z binarną serializacją danych. Ze względu na największą wydajność, na potrzeby implementacji bazy danych \textit{InDB}, zdecydowano się wybrać protokół \textit{TCP}
z binarną serializacją danych. Jak pokazują omówione w następnym rozdziale testy dał on bardzo dobre wyniki wydajnościowe.

\par
Jak zostało ustalone w części projektowej, model danych systemu \textit{InDB} powinien zostać oparty na paradygmacie dokumentowym. Z tego względu należy przyjąć pewien wspólny sposób konwersji 
obiektowych klas na dokumenty. Jak pamiętamy, baza danych \textit{RavenDB} przechowywała wszystkie dane w postaci zbiorów \textit{JSON}. Do ich serializacji oraz deserializacji 
wykorzystywała bardzo dobrą oraz sprawdzona bibliotekę \textit{Json.NET}.

\par
Ze względu na wiele zalet związanych z przejrzystością formatu \textit{JSON} oraz wydajnością biblioteki \textit{Json.NET}, zdecydowano się na zastosowanie w bazie danych \textit{InDB} tego samego
podejścia, co w \textit{RavenDB}. Procesem serializacji oraz deserializacji zajmować się będzie biblioteka kliencka, natomiast w bazie danych dokumenty zapisywane będą w czysto tekstowej formie.

\par
Implementacja systemu \textit{InDB} została oparta o wzorzec wstrzykiwania zależności \cite{fowler}. Zgodnie z jego założeniami klasy nie odwołują się bezpośrednio do siebie, a jedynie do interfejsów,
definiujących pewne funkcjonalności. Istnieją specjalne biblioteki, które w sposób automatyczny potrafią dostarczyć klasy, implementujące odpowiednie interfejsy. Przykładem takiego rozwiązania jest
\textit{Ninject}, który został zastosowany w implementowanym projekcie.


\begin{figure}
\centering
\includegraphics{ioc-overview}
\caption{Graficzna reprezentacja wzorca wstrzykiwania zależności}
\label{ioc-overview}
\end{figure}


\par
Dzięki takiemu podejściu tworzony kod jest znacznie bardziej przejrzysty oraz nieskorelowany ze sobą. Niewątpliwą zaletą jest również znaczne ułatwienie procesu testowania. Zamiast faktycznych klas,
implementujących dane funkcjonalności, można dostarczyć jedynie ich zalążki, sprawdzające, czy dane metody w testowanym interfejsie są faktycznie wywoływane oraz z jakimi parametrami.

\par
Kolejną wspólną częścią serwera oraz biblioteki klienckiej jest sekcja konfiguracyjna, dotycząca adresów oraz roli węzłów w sieci. Zarówno każdy serwer, jak i każdy klient musi posiadać w swoim pliku 
konfiguracyjnym sekcję dotyczącą lokalizacji węzłów. 

\par
Została ona zaimplementowana na bazie standardowego mechanizmu rozbudowy plików konfiguracyjnych aplikacji stworzonych w technologii \textit{.NET}. Jak widać na rysunku \ref{config_section}
składają się na nią trzy klasy.

\begin{figure}
\centering
\includegraphics{configSection}
\caption{Klasy sekcji konfiguracyjnej węzłów}
\label{config_section}
\end{figure}

\par
Najważniejszą z nich jest klasa \textit{HostsConfigurationSection}. Modeluje ona sekcje konfiguracyjną. Posiada jedną metodę \textit{Get}, która pobiera jej instancję na podstawie pliku 
konfiguracyjnego. 

\par
W celu otrzymania listy poszczególnych węzłów należy odwołać się do właściwości \textit{Hosts} klasy sekcji konfiguracyjnej. Jest to obiekt typu \textit{HostCollection}, który modeluje kolekcję 
elementów typu \textit{HostElement}. Elementy te zawierają właściwości \textit{Address} oraz informację dotyczącą roli danego węzła, dzięki czemu można zlokalizować dowolny węzeł w bazie danych.

\par
Na listingu \ref{hostSection} zaprezentowano przykładową zawartość pliku konfiguracyjnego jednego z węzłów. 
Posiada on informację o trzech węzłach, z czego jeden jest typu \textit{master}, natomiast pozostałe są typu \textit{slave}.

\begin{lstlisting}[label=hostSection,caption=Przykładowa konfiguracja węzłów]
<configuration>
  <configSections>    
    <section name="hostsSection" type="InDB.Core.HostsConfigurationSection, 
	InDB.Core" />
  </configSections>
  
  <hostsSection>
    <hosts>
      <clear />
      <add address="192.168.0.12" isMaster="false"/>
      <add address="host-a.example.com" isMaster="false" />
      <add address="master-1.example.com" isMaster="true" />
    </hosts>
  </hostsSection> 
</configuration>
\end{lstlisting}

\subsubsection{Biblioteka kliencka}

Jak zostało to opisane w projekcie, architektura biblioteki klienckiej została oparta na rozwiązaniu \textit{NHibernate}. Każdy ze zdefiniowanych interfejsów został zaimplementowany w odpowiedniej klasie.
Rysunek \ref{client_impl} obrazuje wszystkie najważniejsze klasy w opisywanym projekcie.

\begin{figure}
\centering
\includegraphics{clientImpl}
\caption{Główne klasy implementujące interfejsy biblioteki klienckiej}
\label{client_impl}
\end{figure}

\begin{figure}
\centering
\includegraphics{ConnectionPool}
\caption{Klasy puli gotowych połączeń}
\label{client_connection_pool}
\end{figure}

\par
Jak widać klasa \textit{RestSession} implementuje wszystkie metody interfejsu \textit{ISession}. Dodatkowo posiada ona jedno pole informujące o kontekście transakcji. Jest to identyfikator aktualnej
transakcji. Jeśli transakcja nie została rozpoczęta, ma ono wartość zerową.

\par
Zgodnie z założeniami projektowymi, stworzona została również specjalna klasa \textit{RestTransaction}, która w sposób obiektowy obudowuje operacje związane z transakcją. Jej instancja tworzona jest
poprzez wywołanie metody \textit{BeginTransaction} klasy \textit{RestSession}. W konstruktorze przekazywana jest do niej referencja do tworzącej ją sesji. Dzięki temu, po wykonaniu metody 
\textit{Commit} zatwierdzającej transakcję lub \textit{Dispose} cofającej wszystkie zmiany, jest ona w stanie wywołać odpowiednie metody klasy \textit{RestSession}, bezpośrednio komunikujące się z serwerem.

\par
Kolejnymi bardzo ważnymi klasami są \textit{ServerConnection} oraz \textit{ConnectionPool}. Zgodnie z założeniami projektu, tworzenie instancji klasy implementującej interfejs \textit{ISession}
powinno być bardzo szybkie oraz efektywne. W związku z tym należy do minimum ograniczyć czas związany z połączeniem się do serwera. Najprostszym rozwiązaniem tego problemu jest wprowadzenie
klasy przechowującej pewną ilość otwartych połączeń do serwera. Dzięki temu, w przypadku utworzenia obiektu \textit{RestSession}, poprzez odwołanie się do klasy \textit{ConnectionPool},
otrzymujemy połączenie, które zostało ustanowione już wcześniej i jest gotowe do komunikacji.

\par
Klasa \textit{ConnectionPool} jest stworzona przy wykorzystaniu wzorca projektowego \textit{Singleton}. Został on dokładnie opisany w pracy \cite{singleton}. Dzięki temu mamy pewność, że istnieje tylko
jedna instancja tego obiektu w całej aplikacji. Jest ona odporna na synchroniczny dostęp, więc może być z powodzeniem wykorzystywana w aplikacjach wielowątkowych.

\par
Jej działanie jest następujące. Podczas tworzenia, w konstruktorze, inicjowana jest pewna początkowa ilość połączeń do węzłów typu \textit{master} oraz \textit{slave}. 
Za każdym razem, gdy klasa \textit{RestSession} żąda połączenia, musi podać dodatkowy parametr, mówiący o charakterze połączenia. Jeśli wymaga ono modyfikacji danych, lub rozpoczęcia transakcji
zwracane jest zawsze połączenie do węzła typu \textit{master}. 
W przeciwnym wypadku w sposób losowy zwracane jest połączenie z węzłem typu \textit{slave}. Dzięki takiemu podejściu obciążenie węzłów jest równoważone \cite{random_load_balancer}.

\par
Klasa \textit{ServerConnection} jest realizacją koncepcji pojedynczego połączenia z bazą danych. Zamiast faktycznych połączeń z bazą danych, klasa \textit{ConnectionPool} trzyma w listach referencje
do instancji tej klasy. Warto zauważyć, że jednym z pól tej klasy jest klasa reprezentująca faktyczne połączenie do serwera, \textit{DatabaseWebServiceClient}.

\par
Jeśli klient zażąda dostępu do bazy danych, z odpowiedniej listy usuwana jest jedna instancja klasy połączenia. Ze względu na fakt, że implementuje ona interfejs \textit{IDisposable}, 
w momencie wywołania metody \textit{Dispose} \textit{explicite} lub poprzez zastosowanie konstrukcji \textit{using(...)}, niewykorzystywane połączenie wraca natychmiastowo do puli.


\subsubsection{Serwer bazy danych}

Zgodnie z założeniami projektowymi, serwer aplikacji bazodanowej powinien być niezależnie działającym systemem. Z tego względu zdecydowano się stworzyć go w oparciu o technologię \textit{Windows Service}.
Dzięki temu może on działać nieprzerwanie, w oderwaniu od sesji użytkownika.

\begin{figure}
\centering
\includegraphics{ServiceImpl}
\caption{Główne klasy biblioteki \textit{InDB.Database.Service}}
\label{server_service}
\end{figure}

\par
Jak zostało wspomniane wcześniej baza danych dzieli się na dwie zasadnicze części. Pierwsza z nich odpowiada za uruchamianie oprogramowania w trybie usługi oraz zajmowanie się zgłoszeniami odebranymi przez 
sieć. Rysunek \ref{server_service} obrazuje wszystkie najważniejsze klasy tej części.

\par
Pierwszą z prezentowanych klas jest \textit{Program}. Zawiera ona punkt wejścia dla programu, w postaci procedury \textit{Main}. Jej kod jest zamieszczony na listingu \ref{server_program_main}.

\begin{lstlisting}[label=server_program_main,caption=Kod procedury wejściowej serwera]

static void Main()
{		
	using (var kernel = new StandardKernel(
		new DatabaseCoreModule(),
		new CoreModule(),
		new QueryModule(),                  
		new StorageModule()))
	{
		ServiceBase[] ServicesToRun;
		ServicesToRun = new ServiceBase[] 
		{ 
			kernel.Get<DatabaseService>()
		};
		ServiceBase.Run(ServicesToRun);
	}
}
\end{lstlisting}

\par
Jest on istotny z jednego powodu. Pokazuje, w jaki sposób należy wykorzystywać bibliotekę \textit{Ninject}. 
Zgodnie z założeniami wzorca wstrzykiwania zależności, powinien istnieć tylko jeden obiekt kontenera.
W prezentowanym przykładzie jest on tworzony na początku działania programu i jest źródłem, w którym tworzone są wszystkie instancje. 

\par
Bardzo popularnym błędem, związanym z zastosowaniem biblioteki \textit{Ninject}, jest tworzenie wielu kontenerów. Należy pamiętać, że operacja tworzenia kontenera nie jest zabezpieczona przed 
asynchronicznym wielodostępem. Dodatkowo istnienie więcej niż jednego kontenera zaburza pojęcia zakresów aktywowanych instancji. Jeśli istnieją dwa obiekty kontenera, każdy z nich może niezależnie
aktywować różne instancje klas, które w założeniu powinny być tworzone zgodnie ze wzorcem \textit{singleton}.

\par
Kolejna ważną klasą w implementacji logiki działania aplikacji serwerowej jest \textit{DatabaseService}. Reprezentuje ona pojedynczy serwis, działający jako usługa systemu \textit{Windows}.
Jej metoda \textit{OnStart} zawiera faktyczny kod inicjujący działanie serwisu. Tworzy ona oraz otwiera serwis \textit{WCF}.

\par
Dwie kolejne klasy, \textit{DatabaseWebService} oraz \textit{MasterDatabaseWebService}, stanowią najważniejszy element z punktu widzenia komunikacji z wykorzystaniem opisywanego wcześniej protokołu oraz
technologii \textit{WCF}. W celu pełnego zrozumienia ich znaczenia należy najpierw zrozumieć zasadę działania biblioteki \textit{WCF}.

\par
W celu zainicjowania serwisu należy utworzyć dwa komponenty. Pierwszym z nich jest interfejs, którego metody są opatrzone odpowiednimi atrybutami. Definiuje on operacje, jakie są możliwe do wykonania
przy wykorzystaniu projektowanego serwisu. Drugim z nich jest klasa implementująca ten interfejs. Dostarcza ona faktycznej implementacji zdalnie wywoływanych metod.

\par
Interfejs definiujący operację jest identyczny z zaprezentowanym na rysunku \ref{server_interfaces}. Warto zauważyć, że istnieją dwie klasy implementujące ten interfejs.
Pierwszą z nich jest \textit{DatabaseWebService}. Jest ona wykorzystywana w przypadku, gdy dany węzeł działa w trybie \textit{slave}. Jej implementacja zakłada jedynie, że zapis oraz odczyt odbywać się
będzie bezpośrednio na nośnik danych, z tego powodu nie posiada ona żadnych algorytmów odpowiedzialnych za synchronizację danych.

\par
Jeśli węzeł działa w trybie \textit{master} musi on koordynować modyfikacje danych oraz system transakcji. W tym wypadku jako implementacja interfejsu \textit{IDatabaseWebService} wykorzystywana jest
klasa \textit{MasterDatabaseWebService}. Została ona zaprezentowana na rysunku \ref{server_service}.

\par
W przeciwieństwie do klasy \textit{DatabaseWebService}, po dokonaniu zmian lokalnie synchronizuje je z innymi węzłami typu \textit{slave} w sieci. Warto zauważyć, że dzięki dziedziczeniu tej klasy
po klasie \textit{DatabaseWebService}, implementacja dodatkowej funkcjonalności odbywała się na drodze nadpisywania metod wirtualnych. Jest to bardzo popularny zabieg programistyczny i pozwala na
przyrostowe tworzenie kodu, bez ingerencji w już napisane komponenty.

\par
Jak zostało wspomniane wcześniej, implementacja aplikacji serwerowej dzieli się na dwie główne części. Pierwszą z nich jest \textit{InDB.Database.Service}. Druga nosi nazwę \textit{InDB.Database.Storage} i 
ma za zadanie dostarczyć implementacji mechanizmu trwałego zapisu na dysk.

\par
Jak pamiętamy z rozdziału poprzedniego, baza danych \textit{RavenDB}, jako silnik zapisu danych, wykorzystywała wbudowaną w system \textit{Windows} tabelaryczną bazę danych o nazwie \textit{Esent}.
Jest ona bardzo efektywna oraz wykorzystywana przez wiele produktów firmy \textit{Microsoft}. Ze względu na szereg zalet w postaci prostego \textit{API}, dostępności oraz natywnego wsparcia dla
systemu transakcji, zdecydowano, że aplikacja \textit{InDB} również będzie korzystać z tego mechanizmu, jako silnika zapisu danych.

\begin{figure}
\centering
\includegraphics{EsentClass}
\caption{Klasa implementująca trwały zapis na dysk}
\label{esent_class}
\end{figure}

\begin{figure}
\centering
\includegraphics{EsentTableWrapper}
\caption{Klasa modelująca pojedynczą tabelę w systemie \textit{Esent}}
\label{esent_table_wrapper}
\end{figure}

\par
Na rysunku \ref{esent_class} zaprezentowano klasę \textit{EsentStorage}. Implementuje ona interfejs \textit{IStorage} oraz jest głównym obiektem, mającym za zadanie komunikację z bazą danych \textit{Esent}.
Mankamentem tej bazy jest brak oficjalnego \textit{API} dla platformy \textit{.NET}. Istnieje jednak biblioteka, opakowująca natywne wywołania funkcji \textit{Esent} w odpowiednie klasy.
Nazywa się ona \textit{ManagedEsent} i została również wykorzystana przez twórców bazy danych \textit{RavenDB}. Jej dokładny opis znajduje się w pozycji \cite{managed_esent}.

\par
Mechanizm połączenia do bazy \textit{Esent} jest następujący. Pierwszym krokiem jest stworzenie instancji bazy. Następnie, w zależności od tego czy uruchamiamy program po raz pierwszy czy nie, należy
stworzyć fizyczny plik z bazą danych. Warto zauważyć, że wszystkie dane zapisywane w bazie danych \textit{Esent} umieszczane są w jednym pliku. Po wykonaniu tych operacji możemy przystąpić do modyfikacji
oraz odczytu danych zawartych w bazie.

\par
Należy pamiętać, że \textit{Esent} nie jest relacyjną baza danych. Posiada ona pewne elementy relacyjnych baz danych, jak na przykład tabele oraz indeksy, jednak nie ma możliwość wykonywania
zapytań w języku \textit{SQL}. Istnieją różne mechanizmy pozwalające na przeszukiwanie bazy danych oraz wykonywanie operacji bardzo zbliżonych do fundamentalnych poleceń \textit{SQL}, jednak nie implementuje
ona w żaden sposób tego standardu.

\par
Dostęp do danych w bazie \textit{Esent} jest oparty na kursorach. W celu pobrania lub skasowania pewnego wiersza z tabeli należy utworzyć kursor, a następnie ustawić go w pozycji wskazującej na dany wiersz.
Następnie poprzez polecenia \textit{Delete} lub \textit{Get} można go skasować lub pobrać.

\par
Bardzo ważnym aspektem zastosowania bazy danych \textit{Esent} jest sposób jego wykorzystania. Jak wiadomo baza danych \textit{InDB} posiada dokumentowy model danych, natomiast \textit{Esent} stanowi
tabelaryczny zbiór. Z tego względu należy w jakiś sposób rozwiązać problem konwersji formatów. 
Zdecydowano, że każda kolekcja dokumentów w implementowanej bazie danych znajdzie swoje odzwierciedlenie w tabeli systemu \textit{Esent}. Jest to podejście bardziej zbliżone do 
\textit{MongoDB} niż \textit{RavenDB}, gdzie jak pamiętamy wszystkie kolekcje były przechowywane w jednej tabeli.

\par
Co więcej każda tabela będzie składała się z pięciu kolumn. Dzięki temu metadane oraz faktyczna zawartość dokumentu będą od siebie odseparowane. Poniżej zaprezentowano zbiór wszystkich kolumn.

\begin{itemize}
	\item \textit{Id} - Identyfikator dokumentu, na kolumnie tej zostanie założony główny indeks, w celu przyspieszenia wyszukiwania.
	\item \textit{Version} - Kolumna ta mówi o ilości modyfikacji danego dokumentu.
	\item \textit{LastModified} - Kolumna ta zawiera informację o dacie ostatniej modyfikacji.
	\item \textit{CratedAt} - Kolumna ta zawiera informację o dacie stworzenia dokumentu.
	\item \textit{Content} - Kolumna ta przechowuje zawartości dokumentu w formacie \textit{JSON}.
\end{itemize}

\par
W celu ułatwienia operacji na tabelach stworzono klasę \textit{EsentTableDetails}. Została ona zaprezentowana na rysunku \ref{esent_table_wrapper}. Zawiera identyfikatory tabeli oraz kolumn, 
niezbędne podczas wykonywania operacji na danych zgromadzonych w bazie danych \textit{Esent}. W celu uzyskania dostępu do poszczególnych kolumn w tabeli, należy podać jej nazwę. Z tego względu zdecydowano
się stworzyć wewnętrzną statyczną strukturę o nazwie \textit{ColumnsNames}, która zawierałaby nazwy wszystkich kolumn i udostępniała je w postaci pól statycznych.

\par
Ostatnim elementem aplikacji serwerowej jest instalator. Został on stworzony w oparciu o domyślny projekt instalatora systemu \textit{Windows}. Jego zadaniem jest uproszczenie procesu instalacji 
aplikacji serwerowej, poprzez automatyczne zainstalowanie plików bazy danych oraz zarejestrowanie usługi w systemie \textit{Windows}. 

\par
Warto zauważyć, że w przypadku niepowodzenia procesu instalacji, istnieje możliwość przeprowadzenia jej w sposób ręczny. W tym celu należy wypakować pliki wykonywalne bazy danych oraz wykonać polecenie
zaprezentowane na listingu \ref{manual_installation}. Warto zauważyć, że polecenie \textit{installutil} jest dostępne w każdej wersji \textit{.NET SDK}.

\begin{lstlisting}[label=manual_installation,caption=Instalacja usługi bazy danych \textit{InDB} w systemie \textit{Windows}.]
installutil.exe -i InDb.Database.Service.exe
\end{lstlisting}

\subsection {Podsumowanie}

Stworzenie własnego systemu bazodanowego nie jest zadaniem trywialnym i wymaga dużego wysiłku projektowego oraz dogłębnego zrozumienia specyfiki problemu. Przed przystąpieniem do tworzenia specyfikacji
należy zapoznać się z już istniejącymi rozwiązaniami. Dzięki temu uniknie się najczęstszych błędów oraz pozna najbardziej popularne rozwiązania problemów, z którymi borykają się wszyscy programiści
oraz architekci baz danych.

\par
Na podstawie projektu udało się zaimplementować działający system \textit{InDB}. Co więcej, system ten implementuje całkowitą funkcjonalność opisaną jako specyfikacja wymagań, w szczególności

\begin{itemize}
	\item Został zaimplementowany w oparciu o strukturę klient - serwer.
	\item Występuje brak konieczności mapowania właściwości obiektów na pola w bazie.
	\item Dostąp do danych jest bardzo szybki.
	\item System może zostać rozproszony na wiele węzłów.
	\item Zachowuje się bardzo wydajnie dla dużej ilości krótkich zapytań.
	\item Posiada wsparcie dla transakcji oraz jest łatwy w instalacji.
\end{itemize}

\par
Jedną z najważniejszych czynności, jakie należy wykonać podczas projektowania bazy danych typu \textit{NoSQL}, jest wybór odpowiedniego modelu danych. Każdy z nich posiada bowiem swoje zalety oraz 
wady. Dopiero na podstawie analizy planowanych warunków pracy oraz przeznaczenia można rozstrzygnąć, który z nich będzie optymalny dla projektowanego rozwiązania. 

\par
Warto zauważyć, że jedną z zalet podejścia typu \textit{NoSQL} jest nowe spojrzenie na problem logicznej organizacji informacji. Istnieje wiele aplikacji wymagających przechowywania danych, jednak sposób
ich reprezentacji nie pasuje do modelu relacyjnego. Co więcej, próbując na siłę dopasować ich organizację do modelu relacyjnego, możemy być zmuszeni do napisania dużej ilości kodu konwertującego, 
który nie byłby potrzebny przy zastosowaniu innej technologii.

\par
Dzięki zastosowaniu rozproszonej architektury opartej na podejściu \textit{master - slave} uzyskano możliwość replikacji danych oraz zwiększenia szybkości systemu bazodanowego, poprzez równoczesną 
obsługę żądań przez różne maszyny. Aspekt replikacji oraz zwiększenia wydajności jest szczególnie istotny, jeśli weźmiemy pod uwagę planowane zastosowanie tworzonego systemu. Jedną z najbardziej pożądanych
cech każdego systemu stosowanego w przemyśle jest bezpieczeństwo. Poprzez replikację danych na wiele węzłów, zapewniamy ich integralność oraz trwałość, pomimo potencjalnej awarii jednego z węzłów.

\newpage
\section {Analiza wydajnościowa}

Wydajność, oprócz niezawodności, jest jednym z głównych czynników decydujących o przydatności bazy danych w warunkach produkcyjnych. Wiele baz danych typu \textit{NoSQL} szczyci się bardzo 
wysokim poziomem niezawodności oraz wydajności. Rozdział ten ma na celu weryfikację tej tezy, poprzez przeprowadzenie serii pomiarów wydajnościowych w zestawieniu z relacyjną bazą danych.

\par
Wiele baz danych \textit{NoSQL} znajduje zastosowanie w aplikacjach webowych takich jak portale społecznościowe lub systemy zarządzania treścią. 
Uzasadnione jest to bardzo dużą ilością danych operacyjnych, zgromadzonych w tych systemach, lokalnością tych danych oraz ich modelem, odpowiadającym założeniom baz typu \textit{NoSQL}.

\par
Dobranie odpowiedniej bazy danych dla rozproszonej aplikacji internetowej jest zadaniem nietrywialnym, gdzie główne kryterium stanowi wydajności operacji \textit{CRUD} oraz efektywność 
współdzielenia danych przez węzły w klastrze. 
Co więcej specyfiką tych aplikacji jest generowanie bardzo dużej ilości relatywnie prostych zapytań do bazy danych. W większości przypadków jest to uaktualnienie lub odczytanie pojedynczego 
wiersza z bazy. W przeciwieństwie do zadań zorientowanych na przetwarzanie dużej ilości danych, jak hurtownie danych lub zadania integracji danych, w opisywanych systemach poszczególne 
zapytania nie są ze sobą skorelowane oraz występować mogą w dowolnych odstępach czasu.

\par
Bazy danych typu \textit{NoSQL} są tworem nowym. Oprócz świeżego spojrzenia na model danych, powinny cechować się większą wydajnością niż tradycyjne i sprawdzone rozwiązania. Jedynie w tym przypadku
ich istnienie będzie uzasadnione. Ich analiza wydajnościowa powinna zostać zestawiona z analizą 
wydajnościową pewnej relacyjnej bazy danych. Dzięki temu uzyskamy cały obraz wydajności rozwiązań bazodanowych, nie tylko baz typu \textit{NoSQL}. Na tej podstawie będzie możliwe rozstrzygnięcie,
czy analizowane bazy danych są faktycznie wydajniejsze od rozwiązań istniejących już na rynku od długiego czasu.

\par
Jako przykład relacyjnej bazy danych zdecydowano się wybrać \textit{MSSQL}. Jest to system, który istnieje na rynku już od 1989 roku. Jest on stale rozwijany, najnowsza oficjalna wersja 
została opatrzona numerem \textit{11}. Oprócz samej bazy danych w skład pakietu \textit{MSSQL} wchodzi wiele narzędzi typu \textit{Business Intelligence}, jednak w porównaniu
nie będziemy się nimi zajmować. Skupimy się jedynie na wydajności silnika przechowującego dane. Dostęp do omawianego systemu może być realizowany w dwa sposoby.

\par
Pierwszym z nich jest dostęp przy pomocy standardowych mechanizmów z biblioteki \textit{ADO.NET}. Jest to najbardziej niskopoziomowy sposób dostępu do bazy danych \textit{MSSQL}, oficjalnie wspierany 
przez platformę \textit{.NET}. Z tego względu nie generuje on żadnego narzutu czasowego związanego z mapowaniem obiektowo relacyjnym oraz synchronizacją zależności pomiędzy encjami.

\par
Wadą bezpośredniego dostępu przy pomocy \textit{ADO.NET} jest jednak komplikacja implementacji systemu wykorzystującego to rozwiązanie. 
W przypadku tworzenia aplikacji z rozbudowaną baza danych i złożonym modelem encji, dużo szybciej i łatwiej
zastosować jest gotowe narzędzie typu \textit{ORM}, które automatycznie jest w stanie mapować kolumny do właściwości encji oraz zarządzać zależnościami pomiędzy nimi. 
Przykładem takiego rozwiązania jest \textit{NHibernate} oraz \textit{EntityFramework}, który został wybrany do porównania jako drugi sposób zarządzania danymi zgromadzonymi w \textit{MSSQL}.

\par
Dostęp do wielu obiektowych baz danych odbywa się w bardzo podobny sposób, jak korzystanie z gotowej biblioteki typu \textit{ORM}. Z tego względu zamieszczenie porównania wydajności dostępu do relacyjnej
bazy danych przy pomocy narzędzia typu \textit{ORM} z zastosowaniem obiektowej bazy danych może pokazać, które z rozwiązań w efekcie jest wydajniejsze. Warto zauważyć, że złożoność implementacji 
aplikacji korzystającej z jednego oraz drugiego podejścia jest bardzo zbliżona.

\par
Dodatkowo w porównaniu zdecydowano się zamieścić analizę wydajnościową rozwiązania autorskiego o nazwie \textit{InDB}. Dzięki temu możliwe jest porównanie wydajności prostego rozwiązania, opisywanego
w poprzednim rozdziale, z komercyjnymi oraz sprawdzonymi bazami danych, analizowanymi w rozdziale pierwszym. Warto zauważyć, że analizowany jest jedynie kawałek funkcjonalności opisywanego wcześniej systemu,
związany z szybkością działania metod \textit{CRUD}, najważniejszych z punktu widzenia aplikacji internetowych.

\par
Encje dla każdej bazy były takie same. Pierwsza z nich reprezentowała użytkownika, identyfikowanego przez login, imię oraz identyfikator typu \textit{GUID}.
Druga z nich reprezentowała post danego użytkownika, zawierała ona w sobie również swój identyfikator w postaci typu \textit{GUID}, odniesienie do użytkownika oraz zawartość tekstową reprezentującą
wpis użytkownika.

\par
Dzięki zastosowaniu podejścia \textit{CodeFirst} oferowanego przez \textit{EntityFramework}, generowanie schematu bazy danych \textit{MSSQL} okazało się zbędne. Podejście, wykorzystujące
\textit{ADO.NET}, również korzystało z tego samego wygenerowanego schematu, który w postaci skrótowej został przedstawiony na listingu \ref{sql_tests_createdb}.

\begin{lstlisting}[label=sql_tests_createdb,caption=Polecenia tworzące schemat testowej bazy danych \textit{MSSQL}]
CREATE TABLE [dbo].[Users](
	[Id] [uniqueidentifier] NOT NULL,
	[Login] [nvarchar](max) NULL,
	[Name] [nvarchar](max) NULL)

CREATE TABLE [dbo].[Posts](
	[Id] [uniqueidentifier] NOT NULL,
	[Text] [nvarchar](max) NULL,
	[User_Id] [uniqueidentifier] NULL)
\end{lstlisting}

\par
Do utworzenia schematu bazy danych \textit{Cassandra} wymagane było zdefiniowanie jedynie dwóch rodzin kluczy oraz ich przestrzeni.
Przykład kodu tworzącego tego typu schemat przedstawiono na listingu \ref{cassandra_db_setup}.

\begin{lstlisting}[label=cassandra_db_setup,caption=Polecenia tworzące przestrzeń kluczy oraz super kolumny testowej bazy danych \textit{Cassnadra}]
create keyspace MGR;
create column family Users;
create column family Posts;
\end{lstlisting}

\par
\textit{RavenDB}, \textit{MongoDB} oraz \textit{InDB} nie wymagały żadnych wstępnych przygotowań w celu rozpoczęcia testowania. Są to bazy dokumentowe, kompletnie pozbawione statycznego 
schematu. Kolekcje są tworzone w miarę dodawania nowych dokumentów.

\par
Oprócz założeń strukturalnych testów, bardzo istotnym aspektem jest środowisko, w którym będą się one odbywać. W przypadku pisania tej pracy jest to komputer \textit{PC}
z zainstalowanym systemem operacyjnym \textit{Windows 7 x64}, wyposażony w procesor \textit{Core 2 Duo E7600} o częstotliwości \textit{3.06 GHz} oraz pamięcią \textit{RAM 4GB, 1333MHz}.

\subsection{Analiza szybkości zapisu}

Pierwszą oraz bardzo ważną operacją, którą każda baza danych powinna implementować, jest zapis danych. Jej wydajność jest niezwykle istotna z punktu widzenia systemów logujących wszelką aktywność.
Zazwyczaj potrzebują one w bardzo szybkim tempie zapisywać dane przychodzące z różnych połączeń. Przykładem takiej aplikacji, może być program monitorujący poprawność działania sterownika \textit{PLC}.
Monitoring ten zazwyczaj odbywa się na zasadzie \textit{pollingu}, czyli cyklicznego odpytywania sterownika o jego status. Ze względu na bardzo rygorystyczne obostrzenia czasowe w systemach automatyki, 
zapis ten musi być bardzo szybki. Szybkość odczytu jest mniej istotna, gdyż odbywa się jedynie na żądanie operatora, co w wielu przypadkach zdarza się jedynie podczas awarii lub innych problemów.

\input{Insert}

\par
Wyniki pomiarów wydajności zapisu, badanych baz danych, zostały zgromadzone w tabeli numer \ref{table_Insert}. Procedura testowa była taka sama dla każdej bazy danych. 
W pierwszym kroku wszystkie dane z bazy były usuwane. Następnie tworzonych była pewna, zmienna, ilość encji typu \textit{User} oraz do każdej z nich dodawanych było dziesięć encji typu \textit{Post}.

\par
Jak widać największa szybkością zapisu cechuje się \textit{MongoDB}. Przewaga szybkościowa jest bardzo znacząca nad drugą najszybszą bazą danych w zestawieniu, którą okazało się być rozwiązanie autorskie.
Jak widać \textit{MongoDB} jest około dziesięć razy szybsza niż \textit{InDB} oraz około pięćdziesiąt razy szybsza od najwolniejszej w tym zestawieniu bazy \textit{Cassandra}.

\par
Warto zauważyć, że w przypadku zapisu danych, podejście oparte na \textit{Entity Framework} nie różni się znacznie od zastosowania \textit{ADO.NET}. Dzieje się tak ze względu na bardzo mały narzut 
czasowy związany z przetworzeniem modelu obiektowego na polecenie \textit{SQL} \textit{Insert}.

\par
Bardzo niską szybkością zapisu cechuje się również \textit{RavenDB}. Może być to uwarunkowane dodatkowym narzutem czasowym, 
związanym z brakiem serializacji binarnej przy transferze danych pomiędzy aplikacją 
a bazą danych. Pomimo tego, że podejście takie znacznie upraszcza implementację, okazuje się znacznie mniej wydajne niż zastosowanie alternatywnego podejścia opartego na \textit{BSON}, wykorzystanego
w bazie danych \textit{MongoDB}.

\begin{figure}
\centering
\includegraphics{insert_stats}
\caption{Wykres szybkości dodania \textit{10000} encji \textit{User} i \textit{10} encji \textit{Post} dla poszczególnych baz}
\end{figure}

\FloatBarrier

\subsection{Analiza szybkości odczytu}

Kolejną oraz najważniejszą operacją, którą każda baza danych powinna implementować, jest odczyt danych. Jest ona zwłaszcza istotna dla aplikacji, które cechują się bardzo dużym natężeniem żądań odczytu.
Jest to najczęstszy rodzaj aplikacji, większość operacji w standardowej aplikacji internetowej polega na odczycie danych z bazy. Przykładem takiego systemu może być każdy system zarządzania treścią strony.
Jak wiadomo, modyfikacje na stronach dokonywane są stosunkowo rzadko w stosunku do odczytu danych stron.

\input{GetById}

\par
Wyniki pomiarów szybkości odczytu zostały zamieszczone w tabeli numer \ref{table_GetById}. Procedura testująca była taka sama dla każdej wielkości instancji. W pierwszym kroku zawartość bazy była czyszczona,
następnie było dodawanych \textit{1000} encji typu \textit{User}. W kolejnym kroku wykonywanych było $i$ losowych odczytów encji z bazy danych, na podstawie listy z zapamiętanymi
identyfikatorami poszczególnych encji. Losowane indeksy w tablicy podlegały rozkładowi jednostajnemu.

\par
Jak widać, najszybszym odczytem cechuje się \textit{MSSQL} z dostępem przy pomocy \textit{ADO.NET}. Warto zauważyć, że zastosowanie \textit{Entity Framework} do wykonania dokładnie tego samego zadania
zwiększa czas ponad dwudziestokrotnie. Dzieje się tak ze względu na narzut związany z mapowaniem wyników na encje oraz przetworzeniem polecenia \textit{LINQ} odpowiedzialnego za wyszukanie encji o zadanym
identyfikatorze.

\par
Warto zauważyć, że baza danych \textit{InDB} plasuje się na drugim miejscu w rankingu szybkości odczytu, tuż za \textit{MSSQL}. \textit{MongoDB} plasuje się tuż za bazą danych \textit{InDB}.

\begin{figure}
\centering
\includegraphics{getbyid_stats}
\caption{Wykres szybkości odczytu \textit{10000} encji \textit{User} dla poszczególnych baz}
\end{figure}

\FloatBarrier

\subsection{Analiza szybkości modyfikacji}

Kolejną ważną operacją w systemach internetowych jest możliwość modyfikacji danych. Jest ona bardzo istotna, jednak nie tak często wykorzystywana, jak zapis danych. Jako przykład można przytoczyć
komunikator internetowy, który pozwala na wysłanie wiadomości, jednak nie udostępnia funkcjonalności jej modyfikacji. Baza danych stanowiąca repozytorium archiwum rozmów, właściwie nie musi implementować
możliwości uaktualniania danych

\input{Update}

\par
Wyniki pomiarów szybkości uaktualnienia zamieszczone zostały w tabeli numer \ref{table_Update}. Podobnie jak dla testu szybkości odczytu, w pierwszym kroku cała zawartość bazy danych była czyszczona.
Następnie tworzonych było \textit{1000} encji typu \textit{User}. Kolejnym krokiem było wykonanie $i$ losowych uaktualnień encji z bazy danych.

\par
Jak widać najszybszymi rozwiązaniami, umożliwiającymi modyfikację danych w bazie, są \textit{MSSQL} oraz \textit{MongoDB}. Jest to podyktowane tym, że zarówno język \textit{SQL} jak i biblioteka 
\textit{MongoDB}
umożliwiają wykonanie operacji uaktualnienia bez konieczności wczytywania klasy reprezentującej encję. Efektywnie dzięki temu pomijana jest jedna operacja odczytu z bazy danych.

\par
Biblioteki klienckie \textit{InDB}, \textit{RavenDB} oraz \textit{Entity Framework} są zaprojektowane zgodnie z zasadą propagacji zmian dokonanych w encji na zawartość bazy danych. Jest to bardzo
wygodne z programistycznego punktu widzenia, jednak niesie za sobą dość poważny spadek wydajności, związany z koniecznością odczytania oraz dokonania mapowania wiersza z bazy danych na encję.
Dopiero po wykonaniu tego kroku, można dokonać modyfikacji encji oraz propagacji zmian na bazę danych.
Jak widać w przedstawionym zestawieniu, podejście to wiąże się ze spadkiem wydajności o rząd wielkości czasu potrzebnego na wykonanie operacji.

\begin{figure}
\centering
\includegraphics{update_stats}
\caption{Wykres szybkości modyfikacji \textit{10000} encji \textit{User} dla poszczególnych baz}
\end{figure}

\FloatBarrier

\subsection{Analiza szybkości kasowania}

Kolejną istotną operacją, z punktu widzenia zarządzania danymi zgromadzonymi w bazie, jest operacja kasowania. Nie jest ona tak bardzo popularna jak poprzednie opisywane operacje, jednak
musi być implementowana w każdej bazie danych. Wiele aplikacji internetowych jest zaprojektowanych w sposób, który tak na prawdę nie kasuje fizycznie danych z bazy. Zamiast tego oznacza je jako nie używane.
Dzięki temu zabiegowi dane pozostają w bazie do celów analitycznych, natomiast z punktu widzenia użytkowników są niewidoczne, tak jakby były faktycznie skasowane.

\input{Delete}

\par
Dodatkową zaletą tego typu podejścia jest większa wydajność. Jak widać po wynikach zgromadzonych w tabeli \ref{table_Update} oraz tabeli \ref{table_Delete}, operacja uaktualnienia jest szybsza od 
operacji usunięcia danych. Jest to uwarunkowane koniecznością przeliczenia indeksów oraz, w przypadku relacyjnych baz danych, może wiązać się z koniecznością przebudowania niektórych struktur danych,
w oparciu o które dane są przechowywane.

\par
Procedura testowa nie różniła się od zastosowanej w poprzednich badaniach. Pierwszym krokiem było dodanie $i$ elementów typu \textit{User} do bazy danych, a następnie kasowanie ich po kolei przy użyciu 
oddzielnych połączeń do bazy danych. Identyfikatory encji w bazie danych były zapamiętane podczas tworzenia w specjalnej liście, a następnie w sposób losowy pobierane i przekazywane do funkcji kasującej.

\par
Jak widać w tabeli \ref{table_Delete}, najszybciej dane można usunąć w systemie \textit{MongoDB}. Tuż za nim plasuje się relacyjna baza danych \textit{MSSQL}. Bardzo duża wydajność tych systemów
wiąże się z możliwością usunięcia wiersza lub dokumentu podając jedynie jego identyfikator. W bibliotekach typu \textit{ORM}, jak już zostało wspomniane wcześniej, w większości przypadków nie może się
to odbyć bez wczytania obiektu do pamięci, a następnie usunięcia z bazy danych.

\begin{figure}
\centering
\includegraphics{delete_stats}
\caption{Wykres szybkości kasowania \textit{10000} encji \textit{User} dla poszczególnych baz}
\end{figure}

\FloatBarrier

\subsection{Podsumowanie}

Wydajność jest jedną z kluczowych cech każdej bazy danych. W systemach, gdzie potrzebna jest bardzo duża wydajność, brak tej cechy dyskwalifikuje dane rozwiązanie. Wiele z systemów \textit{NoSQL} szczyci się
dwoma cechami: wydajnością oraz dobrym działaniem w warunkach rozproszonych. 

\par
Rozdział ten miał za zadanie zweryfikować poprawność pierwszej tezy. Jak się okazuje, jest ona prawdziwa, jednak nie dla każdego rozwiązania typu \textit{NoSQL}. W tabeli \ref{table_stats} zgromadzono
pozycje, jakie poszczególne rozwiązania zajęły w testach wydajnościowych. Jasno z niej wynika, że najlepszą bazą danych do operacji zapisu oraz kasowania jest \textit{MongoDB}. Jeśli tworzymy
aplikacje, w której przewidujemy, że będziemy dokonywać wielu odczytów oraz uaktualnień, co w niektórych przypadkach implikuje również logiczne kasowanie danych, najlepiej zastosować tradycyjne 
rozwiązanie w postaci \textit{MSSQL}.

\begin{table}
\centering
\begin{tabular}{ | l |  l  |  l  |  l  |  l  |  l  |  l  | }
\hline & Cassandra & InDB & MongoDB & RavenDB & MSSQL - EF & MSSQL \\
\hline Insert & 6 & 2 & 1 & 5 & 4 & 3 \\
\hline GetById & 5 & 2 & 3 & 4 & 6 & 1 \\
\hline Update & 3 & 4 & 2 & 6 & 5 & 1 \\
\hline Delete & 3 & 4 & 1 & 6 & 5 & 2 \\
\hline
\end{tabular}
\caption{Pozycje poszczególnych systemów bazodanowych w przeprowadzonych testach}
\label{table_stats}
\end{table}


\par
Przeprowadzone testy jasno pokazują, że zastosowanie biblioteki typu \textit{ORM} w postaci \textit{Entity Framework} negatywnie wpływa na wydajność operacji \textit{CRUD}, wykonywanych na bazie danych.
Warto zauważyć, że uzasadnieniem stosowania biblioteki typu \textit{ORM} jest uproszczenie procesu tworzenia aplikacji poprzez zastosowanie automatycznego narzędzia mapującego właściwości klas z modelu 
aplikacji na poszczególne kolumny w bazie danych. Mapowanie takie jest znacznie prostsze, jeśli model bazy danych jest bardziej zbliżony do modelu obiektowego niż model relacyjny.

\par
Jak widać po zbiorczym zestawieniu zaprezentowanym w tabeli numer \ref{table_stats}, baza danych \textit{MongoDB} oprócz bardzo wysokiej wydajności zapewnia również prostotę implementacji aplikacji
klienckich, poprzez umożliwienie zapisu do bazy obiektów typu \textit{POCO}. Dzięki temu łączy ze sobą wydajność takiej bazy jak \textit{MSSQL} z prostotą wykorzystania biblioteki \textit{Entity Framework}.

\par
Bardzo dużym zaskoczeniem okazały się bazy danych \textit{Cassandra} oraz \textit{RavenDB}. Wykazały się one bardzo słabą wydajnością w niemalże wszystkich testowanych operacjach. Jest to zastanawiające,
zwłaszcza w przypadku bazy danych \textit{Cassandra}, której geneza leży w aplikacji \textit{Facebook}. Najprawdopodobniej jej twórcy zdecydowali, że dużo ważniejszy jest dobrze zaprojektowany oraz 
wykonany model funkcjonowania w środowisku rozproszonym, niż wydajność pojedynczego węzła. W takim przypadku brak wydajności można zawsze nadrobić poprzez dodanie kolejnego węzła klastra bazodanowego.

\par
Dodatkowo w aplikacjach rozproszonych bardzo istotna jest wydajność połączenia pomiędzy węzłami. Bazy danych \textit{NoSQL} były w większości projektowane na klastry z dużą ilością węzłów.
Czasami szybkość pojedynczego węzła jest ograniczona przez szybkość połączenia sieciowego pomiędzy nim a serwerem aplikacji. Jednak w wielu przypadkach węzły w klastrach można połączyć na przykład 
światłowodem lub siecią gigabitową, których szybkości znacznie przewyższają prędkość odczytu oraz zapisu danych na dysk, która dla dysków serwerowych jest nie większa niż \textit{100MB/s}.
W ten sposób można wyeliminować mało wydajne połączenie sieciowe.

\par
Wiele bibliotek klienckich analizowanych baz danych zapewnia możliwość wykonywania serii operacji w paczkach. Dzięki temu ich wykonanie jest znacznie szybsze, gdyż występuje tylko jedno połączenie z 
bazą danych. Podejście takie jest jednak ciężkie do zastosowania w aplikacjach webowych, takich jak \textit{Facebook} czy \textit{Twitter}, gdyż występuje w nich wiele pojedynczych, krótkich żądań.
Bardzo istotną cechą bibliotek klienckich baz danych, obsługujących takie serwisy, powinna być pula połączeń. Dzięki temu nie byłby tracony czas na połączenie się z bazą danych.
Jak wiadomo, podejście takie zostało zastosowane w systemie \textit{InDB} i znacznie przyspieszyło jego działanie oraz poprawiło wyniki w testach.

\par
Pomimo bardzo dobrego wsparcia dla funkcjonowania w środowisku rozproszonym, wiele baz danych \textit{NoSQL} nie wykazuje się znacznie większą szybkością działania niż tradycyjne, relacyjne rozwiązanie w 
postaci bazy danych \textit{MSSQL}. Z tego względu, w przypadku, gdy obciążenie pojedynczego węzła jest małe, tak samo jak rozproszenie systemu oraz ilość danych,
lepiej jest zastosować relacyjną bazę danych, która jest sprawdzona oraz bogata w wiele narzędzi administracyjnych oraz bibliotek.
Pewnym wyjątkiem może tutaj być \textit{MongoDB}, które oprócz porównywalnej wydajności oferuje również możliwość zapisywania obiektowych encji wprost do bazy danych, bez konieczności użycia
bibliotek typu \textit{ORM}.

\par
Należy w tym momencie zaznaczyć, że przeprowadzone badania sprawdzały wydajność pojedynczego węzła całego systemu. W normalnych warunkach o wydajności całej bazy danych stanowi również sposób, w jaki została
rozdystrybuowana na wiele węzłów. Wszystkie opisywane systemy były projektowane z myślą o współdziałaniu w środowisku rozproszonym, toteż wyniki tych badań mogą nie być zgodne z badaniami przeprowadzonymi
na odpowiednio rozdystrybuowanym systemie. Niestety ze względów na brak dostępnych środków, badania takie nie mogły zostać przeprowadzone.

\newpage
\section {Podsumowanie}

Relacyjny model danych został zdefiniowany około 1970 roku, to znaczy ponad czterdzieści lat temu, przez Edgara Franka Codda w pracy \cite{relational_model_of_data}. Podejście to stanowiło bardzo
istotny krok w dziedzinie rozwoju technologii bazodanowej. Na jego bazie, w tym samym okresie, firma \textit{IBM} stworzyła system o nazwie \textit{System R}, 
będący pierwszą liczącą się relacyjną bazą danych.

\par
Niedługo później Larry Ellison stworzył ze swoimi znajomymi w firmie \textit{SDL} bazę danych, posiadającą wsparcie dla języka \textit{SQL}. 
Nosiła ona nazwę \textit{Oracle} i odniosła ogromny sukces. Niedługo po tym
na rynku zaczęło pojawiać się coraz więcej relacyjnych baz danych, które były wykorzystywane do gromadzenia coraz większych ilości danych.

\par
Przez lata relacyjne bazy danych wykorzystywane były do agregacji danych, dla których tabelaryczna reprezentacja była oczywista. Przykładem takich zbiorów są dane księgowe, wyniki finansowe oraz notowania
różnych instrumentów finansowych.

\par
Na przestrzeni ponad trzydziestu lat relacyjne bazy danych zupełnie wyeliminowały konkurencję, która prezentowała inne podejście do przechowywania danych. Bazy danych o strukturze obiektowe, grafowej oraz
hierarchicznej zniknęły praktycznie z rynku. Co więcej, coraz większe ilości programistów przyzwyczajały się do modelu relacyjnego.

\par
Lata 90 ubiegłego wieku upłynęły pod znakiem gwałtownego rozwoju internetu oraz systemów informacyjnych. Pojawiło się pojęcie aplikacji z dostępem webowym oraz systemów zarządzania ich treścią.
Wiązało się to oczywiście ze znacznym wzrostem ilości generowanych danych oraz koniecznością efektywnego analizowania oraz przechowywania ich. W tym celu zdecydowano się wykorzystać istniejące, sprawdzone
relacyjne bazy danych.

\par
Niestety od razu zaobserwowano, że obiektowy model danych jakimi operują nowo powstałe systemy internetowe, stworzone w takich językach jak \textit{JAVA} lub \textit{C\#}, nie pasuje do modelu relacyjnego.
Próbowano obejść ten problem poprzez stworzenie specjalnych bibliotek dokonujących mapowania obiektowo relacyjnego jak na przykład \textit{Hibernate}, \textit{SubSonic} czy \textit{EntityFramework}.

\par
Pomimo tego, że niektóre z nich mają już około dziesięciu lat, nie udało się wyeliminować niektórych problemów, a co najważniejsze nie udało się wyeliminować problemu znacznego spadku wydajności
towarzyszącemu ich zastosowaniu.

\par
W pierwszej dekadzie \textit{XXI} wieku w internecie pojawił się zupełnie nowy twór. Były nim portale społecznościowe definiujące erę \textit{WEB 2.0}. Ich fenomen polega na tym, że użytkownik przestał
być odbiorcą prezentowanej treści. Wręcz przeciwnie, w takich portalach jak \textit{Facebook} lub \textit{Twitter}, użytkownicy są jedynymi źródłami generującymi zmiany na stronie.

\par
Jak nietrudno się domyślić, rewolucja ta wiązała się z jeszcze gwałtowniejszym wzrostem ilości informacji, które zarówno z punktu widzenia ekonomicznego, jak i marketingowego były zbyt cenne, aby je utracić.
Systemy tak duże jak \textit{Facebook} są rozdystrybuowane na wiele różnych maszyn i działają na zasadzie klastra obliczeniowego. Jak wiadomo tradycyjne relacyjne bazy danych zostały zaprojektowane
z myślą o pracy na jednej maszynie i posiadają słabo rozbudowany mechanizm funkcjonowania w środowisku rozproszonym.

\par
Z tego względu zdecydowano się spróbować stworzyć nowe systemy bazodanowe, które poprzez poprawione wsparcie dla środowiska rozproszonego oraz odświeżony model danych znacznie lepiej będą nadawać
się do nowych wyzwań, stawianych przed nimi przez portale takie jak \textit{Facebook}, \textit{Twitter} lub \textit{Reddit}. Dało to początek ruchowi \textit{NoSQL}, który agreguje w sobie wszystkie
bazy danych, których twórcy odrzucili założenia standardu \textit{SQL}.

\par
W pracy tej przeanalizowano trzy takie rozwiązania: \textit{RavenDB}, \textit{MongoDB} oraz \textit{Cassandra}. Różniły się one między sobą bardzo znacząco. Zarówno pod względem funkcjonowania w środowisku
rozproszonym, jak i możliwościami konfiguracji oraz wydajności. Co więcej, ta ostatnia cecha została zbadana w trzecim rozdziale. Wyniki tej analizy okazały się zaskakujące. Część z nierelacyjnych baz danych
okazała się wręcz wolniejsza od ich relacyjnej konkurencji. Jest to najprawdopodobniej związane z założeniem przyjętym przez ich twórców, że wydajność systemu zostanie osiągnięta przez efektywne
rozproszenie bazy danych. Wyjątkiem okazała się być baza danych \textit{MongoDB}, która oprócz bardzo dobrej wydajności oferowała użytkownikowi bardzo prosty sposób zapisu obiektowych encji do dokumentowej
bazy danych.

\par
Pośród analizowanych rozwiązań nie znaleziono systemu, który w pełni nadawałby się do zastosowania w warunkach przemysłowych, takich jak akwizycja oraz przechowywanie danych pomiarowych, przy zapewnieniu
odpowiedniej wydajności, stopnia rozproszenia systemu oraz bezpieczeństwa. Z tego względu zdecydowano się stworzyć system o nazwie \textit{InDB},
który łączyłby w sobie zalety wszystkich analizowanych baz danych oraz byłby zorientowany na funkcjonowanie w środowisku przemysłowym. 
Cel ten udało się zrealizować, w szczególności zaprojektowany oraz stworzony system posiada cechy:

\begin{itemize}
	\item Został zaimplementowany w oparciu o strukturę klient - serwer.
	\item Występuje brak konieczności mapowania właściwości obiektów na pola w bazie.
	\item Dostąp do danych jest bardzo szybki.
	\item System może zostać rozproszony na wiele węzłów.
	\item Zachowuje się bardzo wydajnie dla dużej ilości krótkich zapytań.
	\item Posiada wsparcie dla transakcji oraz jest łatwy w instalacji.
\end{itemize}


Co więcej, zaimplementowany system uwzględniono w porównaniu wydajnościowym i wbrew przypuszczeniom, wyniki jego wydajności były lepsze niż niektórych 
istniejących komercyjnych rozwiązań.

\par
Pomimo niezgodności relacyjnego modelu danych ze specyfiką dzisiejszych aplikacji internetowych, wydaje się, że \textit{NoSQL} nie stanowi rozwiązania problemu. Większość z istniejących na rynku rozwiązań
tego typu, jest produktami bardzo młodymi oraz niepozbawionymi wad. Co więcej, nie są one w każdym przypadku znacznie wydajniejsze od sprawdzonych systemów, takich jak \textit{MSSQL}.

\par
W ostatnich latach obserwujemy, że coraz więcej mechanizmów znanych z platform takich, jak \textit{.NET} oraz \textit{JAVA}, dostępnych jest w relacyjnych bazach danych. 
\textit{MSSQL} umożliwia tworzenie procedur wbudowanych za pomocą języka \textit{C\#}, \textit{Oracle} posiada bardzo podobną funkcjonalność, jednak przy wykorzystaniu języka \textit{JAVA}.

\par
Jest bardzo prawdopodobne, że projektanci niektórych relacyjnych baz danych zaczną coraz wyraźniej dostrzegać problem różnicy paradygmatów obiektowego oraz relacyjnego, w kontekście tworzenia
aplikacji internetowych i sami wprowadzą w swoich produktach pewne mechanizmy, ułatwiające ominięcie tego konfliktu. Przykładem kroku w tym kierunku jest umożliwienie pisania procedur składowanych w języku 
\textit{C\#}, w bazie danych \textit{MSSQL}. Rozwiązanie to łączy w sobie zalety uproszczenia oraz skrócenia czasu potrzebnego 
na implementację wielu aplikacji zorientowanych na przetwarzanie danych oraz pozwala wykorzystać sprawdzone, pewne i wydajne rozwiązania, istniejące już na rynku od ponad czterdziestu lat.

\par
Przeprowadzona analiza właściwości nierelacyjnych baz danych pozwala sądzić, że zapotrzebowanie na ich realizację jest pierwszym krokiem w stronę udoskonalenia oraz odświeżenia modelu danych oraz
algorytmów odpowiadających za funkcjonowanie w środowisku rozproszonym, obecnie stosowanych systemów bazodanowych.


\newpage

\bibliography{mgr-bibliography}{}
\bibliographystyle{plain}

 
\end{document}